Rollback is not working in #Transactional annotated service. Spring + Hibernate - spring

In my code the service method savePerson is annotated with #Transactional. Inside this method a Person entity is persisted and inmediately a Runtime exception is intentionally throwed. I suposse the transaction should not be commited but the Person entity is persisted in database....rollback is not working and I dont know why.
This is my Hibernate Configuration:
package newp;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class HibernateConf {
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[]{"newp"});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/poas");
dataSource.setUsername("admin");
dataSource.setPassword("admin");
return dataSource;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
hibernateProperties.setProperty("hibernate.show_sql", "true");
return hibernateProperties;
}
}
This is my service:
package newp.services;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import newp.dao.PersonDao;
import newp.model.Person;
#Service
public class PersonService{
#Autowired
PersonDao dao;
#Transactional
public void savePerson(Person p) {
dao.savePerson(p);
throw new RuntimeException();
}
}
The DAO
package newp.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import newp.entities.PersonEntity;
import newp.model.Person;
#Repository
public class PersonDao {
#Autowired
SessionFactory sessionFactory;
public void savePerson(Person person) {
Session s = sessionFactory.getCurrentSession();
PersonEntity p=new PersonEntity();
p.setAge(person.getAge());
p.setName(person.getName());
p.setSurname(person.getSurname());
s.saveOrUpdate(p);
}
}

You are probably using tables with the MyISAM storage engine which does not support transactions: https://stackoverflow.com/a/8036049/412446

Related

How to support multiple databases engines on Spring?

I’m building a Spring Boot application that should support various databases engines (MySQL, PostgreSQL, Oracle, SQL Server).
The user will be prompted to select which database it would like to use when installing the application and all tables will be created after this. I think that I should save the user option somewhere and then use it to select the right engine that my application will use to instantiate the repositories.
I googled for some references or best practices that I should follow to implement this but wasn’t able to find (maybe I’m searching the wrong terms - sorry).
Do you have any resource that points me to the right direction?
Thanks a lot!!!
You can refer sample. In sample I use hibernate + spring boot for multiple databases.
You can work by this way:
Step 1: you declare in application.properties info connect of database (mysql, oracle, postgresql)
# MySQL-Database
mysql.db.driver: com.mysql.jdbc.Driver
mysql.db.url: jdbc:mysql://localhost:3306/test
mysql.db.username: root
mysql.db.password: root
mysql.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
mysql.entitymanager.packagesToScan: com.test.mysql
# postgresql-Database
postgresql.db.driver: org.postgresql.Driver
postgresql.db.url: jdbc:postgresql://localhost:5432/postgres_demo
postgresql.db.username: root
postgresql.db.password:
postgresql.hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect
postgresql.entitymanager.packagesToScan: com.test.postgresql
# Oracle-Database
oracle.db.driver: oracle.jdbc.driver.OracleDriver
oracle.db.url: jdbc:oracle:thin:#localhost:1521:xe
oracle.db.username: root
oracle.db.password:
oracle.hibernate.dialect: org.hibernate.dialect.Oracle10gDialect
oracle.entitymanager.packagesToScan: com.test.oracle
Step 2: In project spring boot you can refer structure project such as:
Step 3 : Implement data source for mysql, oracle, postgresql. you can refer MysqlDatabaseConfig.java, OracleDatabaseConfig.java, PostgresDatabaseConfig.java
package com.test.mysql;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class MysqlDatabaseConfig {
#Value("${mysql.db.driver}")
private String DB_DRIVER;
#Value("${mysql.db.password}")
private String DB_PASSWORD;
#Value("${mysql.db.url}")
private String DB_URL;
#Value("${mysql.db.username}")
private String DB_USERNAME;
#Value("${mysql.hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${mysql.entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Bean(name="mysqlDataSource")
#Primary
public DataSource cmrDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
#Bean(name="mysqlSessionFactory")
public LocalSessionFactoryBean crmSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(cmrDataSource());
sessionFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean(name="mysqlTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(crmSessionFactory().getObject());
return transactionManager;
}
}
OracleDatabaseConfig.java
package com.test.oracle;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
public class OracleDatabaseConfig {
#Value("${oracle.db.driver}")
private String DB_DRIVER;
#Value("${oracle.db.password}")
private String DB_PASSWORD;
#Value("${oracle.db.url}")
private String DB_URL;
#Value("${oracle.db.username}")
private String DB_USERNAME;
#Value("${oracle.hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${oracle.entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Bean(name="oracleDataSource")
#Primary
public DataSource cmrDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
#Bean(name="oracleSessionFactory")
public LocalSessionFactoryBean crmSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(cmrDataSource());
sessionFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean(name="oracleTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(crmSessionFactory().getObject());
return transactionManager;
}
}
PostgresDatabaseConfig.java
package com.test.postgresql;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
public class PostgresDatabaseConfig {
#Value("${postgresql.db.driver}")
private String DB_DRIVER;
#Value("${postgresql.db.password}")
private String DB_PASSWORD;
#Value("${postgresql.db.url}")
private String DB_URL;
#Value("${postgresql.db.username}")
private String DB_USERNAME;
#Value("${postgresql.hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${postgresql.entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Bean(name="postgresqlDataSource")
#Primary
public DataSource cmrDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
#Bean(name="postgresqlSessionFactory")
public LocalSessionFactoryBean crmSessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(cmrDataSource());
sessionFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean(name="postgresqlTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(crmSessionFactory().getObject());
return transactionManager;
}
}
Step 4: call to use:
in case mysql
package com.test.mysql.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
#Repository
#Transactional("mysqlTransactionManager")
public class TestMysqlDao {
#Autowired
#Qualifier("mysqlSessionFactory")
private SessionFactory sessionFactory;
}
In case oracle
package com.test.oracle.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
#Repository
#Transactional("oracleTransactionManager")
public class TestOracleDao {
#Autowired
#Qualifier("oracleSessionFactory")
private SessionFactory sessionFactory;
}
In case postgresql
package com.test.postgresql.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
#Repository
#Transactional("postgresqlTransactionManager")
public class TestPostgresDao {
#Autowired
#Qualifier("postgresqlSessionFactory")
private SessionFactory sessionFactory;
}
It's unclear what you mean by installing but if you want your application to start with different databases you can use different Spring profiles with your application.yml Spring boot profiles
---
spring:
profiles: postgres
datasource:
url:
username:
password:
driver-class-name: org.postgresql.Driver
---
spring:
profiles: mysql
datasource:
url:
username:
password:
driver-class-name: com.mysql.jdbc.Driver
You can then start the application with the respective profile
java -jar -Dspring.profiles.active=mysql yourapp.jar
You can define different connections and get them with specific methods
private DataSource mySqlDataSource;
private DataSource postgresDataSource;
public Connection getMySqlConnection() throws SQLException {
mySqlDataSource.getConnection();
}
public Connection getPostgresConnection() throws SQLException {
postgresDataSource.getConnection();
}

when using miltiple datasource hibernate envers are not working

When I use only one datasource, hibernate envers are working well(not using any config.java. just set application.properties). But Using multiple datasource(with config.java, same DB, different user), envers are not working and logged oracle error message ORA-00942.
audited table is in DB#1. How can I do?
spring boot 1.5.6
application.properties
#################################
# DataBase #1 (Default)
#################################
spring.datasource.initialize=true
spring.datasource.url=jdbc:oracle:thin:#localhost:1521:orcl
spring.datasource.username=id_1
spring.datasource.password=pw_1
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#################################
# DataBase #2(Additional)
#################################
db2.datasource.initialize=true
db2.datasource.url=jdbc:oracle:thin:#localhost:1521:orcl
db2.datasource.username=db_2
db2.datasource.password=pw_2
db2.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
config.java
package com.dev;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
#Configuration
public class DataBaseConfig {
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource defaultDataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "defaultEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(defaultDataSource())
.packages("com.dev.core.**", "com.dev.ext.**")
.build();
}
#Primary
#Bean(name = "defaultTransactionManager")
PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactory(builder).getObject());
}
#Configuration
#EnableJpaRepositories(basePackages= {"com.dev.core.**", "com.dev.ext.**"},
entityManagerFactoryRef = "defaultEntityManagerFactory", transactionManagerRef = "defaultTransactionManager")
static class DefaultJpaRepositoriesConfig {
}
/*Additional Data Source - NCRM*/
#Bean
#ConfigurationProperties(prefix = "db2.datasource")
public DataSource ncrmDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "ncrmEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean ncrmEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(ncrmDataSource())
.packages("com.dev.ext.ncrm.*.domain")
.build();
}
#Bean(name = "ncrmTtransactionManager")
PlatformTransactionManager ncrmTransactionManagerMain(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(ncrmEntityManagerFactory(builder).getObject());
}
#Configuration
#EnableJpaRepositories(
basePackages="com.dev.ext.ncrm.*.repo",
entityManagerFactoryRef = "ncrmEntityManagerFactory",
transactionManagerRef = "ncrmTtransactionManager")
static class ncrmJpaRepositoriesConfig {
}
}
defaultDO.java
package com.dev.core.domain;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
import lombok.Data;
#Data
#Entity
#Table(name = "tb_category")
#Audited
#AuditTable("tx_category_audit")
public class CategoryDO {
//codes
}
First add hibernate dialect at application.properties file like below for both data source:
spring.datasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
spring.secondDatasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
Then Please rewrite the configuration like below
package com.multisource.poc.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
public class ApplicationConfiguration {
#Value("${spring.datasource.hibernate.dialect}")
private String oracleDialect;
#Value("${spring.secondDatasource.hibernate.dialect}")
private String postgresDialect;
#Primary
#Bean(name = "oracleDB")
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "oracleEM")
public LocalContainerEntityManagerFactoryBean oracleEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", oracleDialect);
LocalContainerEntityManagerFactoryBean emf = builder
.dataSource(oracleDataSource())
.packages("entitypackageOne")
.persistenceUnit("oraclePU")
.build();
emf.setJpaProperties(properties);
return emf;
}
#Bean(name = "postgresDB")
#ConfigurationProperties(prefix = "spring.secondDatasource")
public DataSource postgresDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "postgresEM")
public LocalContainerEntityManagerFactoryBean postgresEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", postgresDialect);
LocalContainerEntityManagerFactoryBean emf = builder
.dataSource(postgresDataSource())
.packages("entitypackageTwo")
.persistenceUnit("postgresPU")
.build();
emf.setJpaProperties(properties);
return emf;
}
}
Now you have two different EntityManager to use. The sample would be like
#Repository
public class OracleDao implements InterOracle {
private EntityManager entityManager;
#Autowired
public OracleDao(#Qualifier("oracleEM") EntityManager entityManager) {
this.entityManager = entityManager;
}
}
#Repository
public class PostgresDao implements InterPostGres{
private static final Logger LOG
= LoggerFactory.getLogger(PostgresDao.class);
private EntityManager entityManager;
#Autowired
public PostgresDao(#Qualifier("postgresEM") EntityManager entityManager) {
this.entityManager = entityManager;
}
}
This is how my application is working using two different datasource.
Does user db_2 / pw_2 have the required permission to access the DB?

Pros and cons of changing autocommit=true in spring boot application?

To me it looks like autocommit is completely overridden with Spring-Hibernate configuration and this property absolutely doesn't play any role in such a configuration but I would like to confirm that somehow.
Spring boot 1.5.10.RELEASE version. Database is PostgreSQL 9.5.6.
Datasource configuration
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
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 javax.persistence.EntityManagerFactory;
import java.util.Properties;
#Configuration
public class DataSourceConfig {
private Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName(driver);
driverManagerDataSource.setUrl(url);
driverManagerDataSource.setUsername(username);
driverManagerDataSource.setPassword(password);
return driverManagerDataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { domainModelNamespace });
em.setJpaProperties(additionalProperties());
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.show_sql", showSql);
properties.setProperty("hibernate.dialect", dialect);
properties.setProperty("hibernate.hbm2ddl.auto", hbm2ddl);
return properties;
}
}
And here is test method
import com.phonebook.IntegrationTest;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.sql.DataSource;
import java.sql.SQLException;
public class DataSourceTesting extends IntegrationTest{
#Autowired
private DataSource dataSource;
Logger logger = LoggerFactory.getLogger(DataSourceTesting.class);
#Test
public void testDataSourceConnectionProperties() throws SQLException {
boolean autoCommit = dataSource.getConnection().getAutoCommit();
Assert.assertFalse(autoCommit);
}
}
The question is what autocommit means in this context? In test it is on
true
as well as in #Transactional method checking it in debug mode.

Change #PersistenceContext to #PersistenceUnit while running Junit tests

I am using #PersistenceContext as of now and working fine. However the same application need to be used in Junit context as well. I want #PersistenceContext to be changed to #PersistenceUnit in DaoImpl classes when Junit test cases are running. How to do that?
Using the following versions in my application
<springframework.version>4.2.5.RELEASE</springframework.version>
<hibernate.version>5.1.0.Final</hibernate.version>
<hibernate.validator.version>5.2.4.Final</hibernate.validator.version>
<mysql.connector.version>6.0.3</mysql.connector.version>
<junit.version>4.12</junit.version>
Hibernate Configuration is:
package com.rsa.springwebclasses.configuration.db;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
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;
import ch.qos.logback.classic.Logger;
#Configuration
#EnableTransactionManagement
#PropertySources({
#PropertySource("classpath:hibernate/hibernate.properties"),
#PropertySource("classpath:mysql/mysql.properties")
})
public class HibernateConfiguration {
Logger logger = (Logger) LoggerFactory.getLogger(HibernateConfiguration.class);
#Autowired
Environment env;
private Properties getHibernateProperties() {
Properties hprop = new Properties();
hprop.put("hibernate.dialect", env.getRequiredProperty("mysql.hibernate.dialect"));
hprop.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
hprop.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
logger.info("Hibernate properties: " + hprop.toString());
return hprop;
}
private Properties getMysqlProperties() {
Properties mySqlProp = new Properties();
mySqlProp.put("jdbc.driverClassName", env.getRequiredProperty("mysql.jdbc.driverClassName"));
mySqlProp.put("jdbc.url", env.getRequiredProperty("test.mysql.jdbc.url"));
mySqlProp.put("jdbc.username", env.getRequiredProperty("test.mysql.jdbc.username"));
mySqlProp.put("jdbc.password", env.getRequiredProperty("test.mysql.jdbc.password"));
logger.info("MySQL properties: " + mySqlProp.toString());
return mySqlProp;
}
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
Properties dbProp = this.getMysqlProperties();
dataSource.setDriverClassName(dbProp.getProperty("jdbc.driverClassName"));
dataSource.setUrl(dbProp.getProperty("jdbc.url"));
dataSource.setUsername(dbProp.getProperty("jdbc.username"));
dataSource.setPassword(dbProp.getProperty("jdbc.password"));
logger.info("DataSource object is created.");
return dataSource;
}
#Bean
public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(emf);
logger.info("PlatformTransactionManager is initialized with JpaTransactionManager");
return jtm;
}
#Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(getDataSource());
emfb.setPackagesToScan(new String[] {"com.rsa.springwebclasses.model"});
JpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
emfb.setJpaVendorAdapter(vendor);
emfb.setJpaProperties(getHibernateProperties());
logger.info("LocalContainerEntityManagerFactoryBean created: PersistentUnit Name: " + emfb.getJpaVendorAdapter().toString());
return emfb;
}
}
My DaoImpl class is:
package com.rsa.springwebclasses.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.rsa.springwebclasses.dao.UserDao;
import com.rsa.springwebclasses.model.User;
import ch.qos.logback.classic.Logger;
#Repository("userDao")
public class UserDaoImpl implements UserDao {
Logger logger = (Logger) LoggerFactory.getLogger(UserDaoImpl.class);
**#PersistenceContext**
EntityManager em;
public List<User> findAllUsers() {
logger.debug("In findAllUsers method.");
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = cb.createQuery(User.class);
Root<User> user = criteria.from(User.class);
criteria.select(user).orderBy(cb.asc(user.get("username")));
logger.debug("Exit findAllUsers method");
return em.createQuery(criteria).getResultList();
}
}
While injecting EntityManager, #PersistenceContext is hard coded. However the same DaoImpl class need to be used for Junit test cases as well. With Junit I prefer to use transaction type as RESOUCE_LOCAL which is possible only with #PersistenceUnit. Is it possible to have a different annotation in DaoImpl class and assign #PersistenceContext or #PersistenceUnit while application is loading or already running?

Spring security 3.2.5 and token based authentication

I'm trying to secure a REST API using Spring security 3.2.5 and a java based configuration.
Actually i've found many examples developed with an "old" xml approach, but nothing with a complete java configuration.
Where can i find some useful tutorial?
The project creates a REST API and some jsp usesd to allow the admin to populate an underlyin DB (Hibernate is used as ORM):
Here is my Config class:
package com.idk.fantappapaback.spring;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource; 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.Import; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.multipart.support.StandardServletMultipartResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.JstlView; import org.springframework.web.servlet.view.UrlBasedViewResolver;
import com.google.common.base.Preconditions; import com.idk.fantappapaback.spring.security.SecurityConfig;
#Configuration #EnableWebMvc #EnableTransactionManagement #PropertySource({ "classpath:persistence-mysql.properties" }) #ComponentScan({ "com.idk.fantappapaback.persistence","com.idk.fantappapaback.rest","com.idk.fantappapaback.spring.controllers","com.idk.fantappapaback.spring.security" }) #Import({ SecurityConfig.class }) public class BackEndConfig extends WebMvcConfigurerAdapter{
#Autowired
private Environment env;
public BackEndConfig() {
super();
}
//l'application context estrae il session factory da questo bean
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.idk.fantappapaback.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) {
final HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
//***Proprieta per l'output delle query in sql che qui disabilito
// hibernateProperties.setProperty("hibernate.show_sql", "true");
// hibernateProperties.setProperty("hibernate.format_sql", "true");
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
return hibernateProperties;
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public StandardServletMultipartResolver multipartResolver(){
return new StandardServletMultipartResolver();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/"); // registry.addResourceHandler("/css/**") // .addResourceLocations("/css/"); // registry.addResourceHandler("/img/**") // .addResourceLocations("/img/");
registry.addResourceHandler("/js/**")
.addResourceLocations("/js/");
}
}
this is my very basic Security config that i use to have a form log in on the jsp views:
package com.idk.fantappapaback.spring.security;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Import({ SecurityConfig.class }) nella BackEndConfig #Configuration #EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter{ #Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("USER"); // auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("ADMIN"); auth.inMemoryAuthentication().withUser("masquenada").password("123456").roles("SUPERADMIN"); }
#Override protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // .antMatchers("/players/**").access("hasRole('ROLE_USER')") .antMatchers("/createSeason/**").access("hasRole('ROLE_SUPERADMIN')") .and().formLogin().permitAll() .and().httpBasic();
} }
here is my SecurityWebApplicationInitializer :
package com.idk.fantappapaback.spring.security;
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
The main question is : how to add the token based autorization?
I've added Spring oAuth 2 and Spring integration to my pom but i need some hint about introducing spring oAuth keeping the form login.
You need to "configure" your SecurityWebApplicatioInitializer.
http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/

Resources