java.lang.NoClassDefFoundError: org/springframework/orm/hibernate4/SpringSessionContext - spring

I am try to implement SpringMVC 4 and Hibernate 4 integration with annotation in my project but I am getting this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.config.ApplicationContextConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.hibernate.SessionFactory]: Factory method 'getSessionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/orm/hibernate4/SpringSessionContext
My Config file is::
import javax.sql.DataSource;
import java.util.Properties;
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.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.orm.hibernate4.SpringSessionContext;
import com.dao.UserDao;
import com.dao.UserDaoImpl;
import com.pojo.User;
#Configuration
#ComponentScan("com.config")
#EnableTransactionManagement
public class ApplicationContextConfig {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/usersdb");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addAnnotatedClasses(User.class);
return sessionBuilder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
return properties;
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(
sessionFactory);
return transactionManager;
}
#Autowired
#Bean(name = "userDao")
public UserDao getUserDao(SessionFactory sessionFactory) {
return new UserDaoImpl(sessionFactory);
}
}

It appears that you need, but do not have spring-orm-4.3.0.RELEASE.jar on your classpath. (I have identified the 4.3.0 version, you may be using a different 4.X version).
If you are using Maven, add the appropriate dependency to your pom.xml.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.0.RELEASE</version>
<scope>runtime</scope>
</dependency>
If you are not using Maven, you can download the jar file here.
For information on setting the classpath see this section of the Java Tutorial.

Related

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

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

Spring boot: I need an explanation for a few lines of code

I am studying spring boot, and am failing to understand a few lines of code.
Referring to the code below, I would like to understand what is needed
#ComponentScan ("boot.entry")
and these two lines declared in the transactionManager() method, that is
HibernateTransactionManager txManager = new HibernateTransactionManager ();
txManager.setSessionFactory (sessionFactory (). getObject ());
Can anyone kindly help me?
package config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableTransactionManagement
#EnableAutoConfiguration(exclude = { HibernateJpaAutoConfiguration.class})
#ComponentScans(value = { #ComponentScan("boot.entry"),
#ComponentScan("Model"),
#ComponentScan("Controller"),
#ComponentScan("DAO"),
#ComponentScan("Miscallaneous"),
#ComponentScan("Service")})
public class Config {
#Value("${db.driver}")
private String DB_DRIVER;
#Value("${db.password}")
private String DB_PASSWORD;
#Value("${db.url}")
private String DB_URL;
#Value("${db.username}")
private String DB_USERNAME;
#Value("${hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${hibernate.show_sql}")
private String HIBERNATE_SHOW_SQL;
#Value("${hibernate.hbm2ddl.auto}")
private String HIBERNATE_HBM2DDL_AUTO;
#Value("${entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
hibernateProperties.put("hibernate.hbm2ddl.auto", HIBERNATE_HBM2DDL_AUTO);
sessionFactory.setHibernateProperties(hibernateProperties);
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
#Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver resolver= new InternalResourceViewResolver();
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
#ComponentScan ("boot.entry")
#ComponentScan basically instruct the Spring IoC to track down the entities for dependency injection.
HibernateTransactionManager txManager = new HibernateTransactionManager ();
txManager.setSessionFactory (sessionFactory (). getObject ());
HibernateTransactionManager handles the transaction handling which requires HibernateSession which is basically an instance of datasource wrapped within JPA specification to handle OOP oriented query handling.
#ComponentScan ("boot.entry") Means that It should load all Components (Beans, Services etc) inside the boot.entry package, which probably should be contained in your project.
Hibernate is an ORM library that lets you do SQL queries without writing SQL. What you are doing in your code is basically initializing the transactionManager with the data from the sessionFactory() function.

Hibernate exception when try to launch Tomcat

I have application on spring-mvc+jpa. I build war and try to start on tomcat.
DataConfig:
import org.hibernate.ejb.HibernatePersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:app.properties")
public class DataConfig {
private static final String PROP_DATABASE_DRIVER = "db.driver";
private static final String PROP_DATABASE_URL = "db.url";
private static final String PROP_DATABASE_USERNAME = "db.username";
private static final String PROP_HIBERNATE_DIALECT = "db.hibernate.dialect";
private static final String PROP_HIBERNATE_SHOW_SQL = "db.hibernate.show_sql";
private static final String PROP_ENTITYMANAGER_PACKAGES_TO_SCAN = "db.entitymanager.packages.to.scan";
private static final String PROP_HIBERNATE_HBM2DDL_AUTO = "db.hibernate.hbm2ddl.auto";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROP_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROP_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROP_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty("db.password"));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setDataSource(dataSource());
entityManager.setPackagesToScan(env.getRequiredProperty(PROP_ENTITYMANAGER_PACKAGES_TO_SCAN));
entityManager.setPersistenceProviderClass(HibernatePersistence.class);
entityManager.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManager.setJpaProperties(getHibernateProperties());
return entityManager;
}
#Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put(PROP_HIBERNATE_DIALECT, env.getRequiredProperty(PROP_HIBERNATE_DIALECT));
properties.put(PROP_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROP_HIBERNATE_SHOW_SQL));
properties.put(PROP_HIBERNATE_HBM2DDL_AUTO, env.getRequiredProperty(PROP_HIBERNATE_HBM2DDL_AUTO));
return properties;
}
}
app.properties is:
#DB properties:
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/mydb
db.username=root
db.password=111111
#Hibernate Configuration:
db.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
db.hibernate.show_sql=true
db.entitymanager.packages.to.scan=ru.sbrf.risks.services.data.model
db.hibernate.hbm2ddl.auto = create-drop
So, there is error message in tomcat logs:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit:
default] Unable to build EntityManagerFactory at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:924)
at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:899)
at
org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:76)
at
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:287)
at
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 57 more Caused by: org.hibernate.HibernateException: Connection
cannot be null when 'hibernate.dialect' not set at
org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:97)
at
org.hibernate.service.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:67)
at
org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:170)
at
org.hibernate.service.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:75)
at
org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:159)
at
org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)
at
org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1818)
at
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1776)
at
org.hibernate.ejb.EntityManagerFactoryImpl.(EntityManagerFactoryImpl.java:96)
at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914)
... 63 more
Hibernate doesn't understand the properties you are passing it. You have hibernate.dialect defined as db.hibernate.dialect Remove the db portion and just have it as hibernate.dialect and do the same with your other hibernate related properties.
https://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/session-configuration.html
#PropertySource("classpath:app.properties")
This annotation value replace with below passing value
#PropertySource(value = {"classpath:application.properties","file:config/application.properties"}, ignoreResourceNotFound = true)
and rebuild you project.now it's working fine.

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.

Two EntityManagerFactories, TransactionRequiredException: no transaction is in progress

The Spring MVC application uses SpringDataJPA and hibernate. The production mode leverages MySQL but for the unit tests I have set up H2DB to run, both with separate java configuration. The application also utilizes Spring Security but its configuration I omitted below.
The appliaction starts up with the unit tests but at the first test (testOIC() see in the below code) I got the "TransactionRequiredException: no transaction is in progress".
testException = org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress, mergedContextConfiguration = [WebMergedContextConfiguration#1c581a0 testClass = OpenPositionsServiceTest, locations = '{}', classes = '{class our.dcollect.configuration.AppConfiguration, class our.dcollect.configuration.HibernateConfigurationTest}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]].
The unit test I run with Propagation.REQUIRES_NEW, so it should have a transaction context. I am afraid I messed up something in the appliaction context. The posts I found in connection with this topic did not help a lot.
The ApplicationContext contains the following beans:
Spring Bean Definition Names in ApplicationContext (applicationContext.getBeanDefinitionNames()):
===================================================
Bean: appConfiguration
Bean: authenticationManagerBuilder
Bean: autowiredWebSecurityConfigurersIgnoreParents
Bean: beanNameHandlerMapping
Bean: dataSource
Bean: dataSourceTest
Bean: defaultServletHandlerMapping
Bean: delegatingApplicationListener
Bean: dtoConverter
Bean: emBeanDefinitionRegistrarPostProcessor
Bean: enableGlobalAuthenticationAutowiredConfigurer
Bean: entityManagerFactory
Bean: entityManagerFactoryTest
Bean: fileUploadController
Bean: fileUploadService
Bean: getInternalResourceViewResolverJsp
Bean: handlerExceptionResolver
Bean: hibernateConfiguration
Bean: hibernateConfigurationTest
Bean: hibernateProperties
Bean: httpRequestHandlerAdapter
Bean: initializeAuthenticationProviderBeanManagerConfigurer
Bean: initializeUserDetailsBeanManagerConfigurer
Bean: jpaContext
Bean: jpaMappingContext
Bean: jpaVendorAdapter
Bean: jpaVendorAdapterTest
Bean: multipartResolver
Bean: mvcContentNegotiationManager
Bean: mvcConversionService
Bean: mvcPathMatcher
Bean: mvcResourceUrlProvider
Bean: mvcUriComponentsContributor
Bean: mvcUrlPathHelper
Bean: mvcValidator
Bean: mvcViewResolver
Bean: objectPostProcessor
Bean: openIn....Repository
Bean: openPositionsService
Bean: org.springframework.aop.config.internalAutoProxyCreator
Bean: org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
Bean: org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
Bean: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
Bean: org.springframework.context.annotation.internalCommonAnnotationProcessor
Bean: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
Bean: org.springframework.context.annotation.internalPersistenceAnnotationProcessor
Bean: org.springframework.context.annotation.internalRequiredAnnotationProcessor
Bean: org.springframework.context.event.internalEventListenerFactory
Bean: org.springframework.context.event.internalEventListenerProcessor
Bean: org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension#0
Bean: org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport_Predictor
Bean: org.springframework.orm.jpa.SharedEntityManagerCreator#0
Bean: org.springframework.orm.jpa.SharedEntityManagerCreator#1
Bean: org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
Bean: org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
Bean: org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration
Bean: org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
Bean: org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
Bean: org.springframework.transaction.config.internalTransactionAdvisor
Bean: org.springframework.transaction.config.internalTransactionalEventListenerFactory
Bean: org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
Bean: privilegeEvaluator
Bean: push....Repository
Bean: requestDataValueProcessor
Bean: requestMappingHandlerAdapter
Bean: requestMappingHandlerMapping
Bean: resourceHandlerMapping
Bean: securityConfiguration
Bean: sessionFactory
Bean: sessionFactoryTest
Bean: simpleControllerHandlerAdapter
Bean: springSecurityFilterChain
Bean: transactionAttributeSource
Bean: transactionInterceptor
Bean: transactionManager
Bean: transactionManagerTest
Bean: viewControllerHandlerMapping
Bean: webSecurityExpressionHandler
===================================================
Could you help? The relevant code parts I posted below.
MVC configuration:
package our.dcollect.configuration;
import org.apache.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "our.dcollect")
public class AppConfiguration {
private static final Logger log = Logger.getLogger(AppConfiguration.class);
#Bean
public InternalResourceViewResolver getInternalResourceViewResolverJsp(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(0);
log.info("#### Internal view resolver 0 called...");
return viewResolver;
}
#Bean
public StandardServletMultipartResolver multipartResolver(){
log.info("#### Multipart resolver called...");
return new StandardServletMultipartResolver();
}
}
Hibernate Configuration:
package our.dcollect.configuration;
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.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#ComponentScan(basePackages = "our.dcollect")
#EnableJpaRepositories(basePackages = {"our.dcollect.repository"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager")
#PropertySource(value = { "classpath:application.properties" })
#EnableTransactionManagement
//#PropertySource({ "/resources/hibernate.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean(name="sessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "our.dcollect" });
sessionFactory.setHibernateProperties(this.hibernateProperties());
return sessionFactory;
}
#Bean(name="dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
#Bean(name="hibernateProperties")
public 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.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
}
#Bean(name="transactionManager")
#Autowired
public HibernateTransactionManager transactionManager(#Qualifier("sessionFactory") SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
#Bean(name="jpaVendorAdapter")
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(true);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
return hibernateJpaVendorAdapter;
}
#Bean(name="entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(this.dataSource());
lef.setJpaProperties(this.hibernateProperties());
lef.setJpaVendorAdapter(this.jpaVendorAdapter());
lef.setPackagesToScan(new String[] { "our.dcollect.model"});
return lef;
}
}
Hibernate Configuration for the Unit Tests:
package our.dcollect.configuration;
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.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/***************************************************************************************
* The same as the real HibernateConfiguration but this works with H2 DB instead of MySQL.
* In addition, the properties are not read from a property file.
****************************************************************************************/
#Configuration
#ComponentScan(basePackages = "our.dcollect")
#EnableJpaRepositories(basePackages = {"our.dcollect.repository"},
entityManagerFactoryRef = "entityManagerFactoryTest",
transactionManagerRef = "transactionManagerTest")
#PropertySource(value = { "classpath:application.properties" })
#EnableTransactionManagement
public class HibernateConfigurationTest {
#Bean(name = "sessionFactoryTest")
public LocalSessionFactoryBean sessionFactoryTest() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSourceTest());
sessionFactory.setPackagesToScan(new String[] { "our.dcollect" });
sessionFactory.setHibernateProperties(hibernatePropertiesTest());
return sessionFactory;
}
#Bean(name = "dataSourceTest")
public DataSource dataSourceTest() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("...");
dataSource.setPassword("...");
return dataSource;
}
private Properties hibernatePropertiesTest() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
}
#Bean(name = "transactionManagerTest")
#Autowired
public HibernateTransactionManager transactionManagerTest(#Qualifier("sessionFactoryTest") SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
#Bean(name = "jpaVendorAdapterTest")
public JpaVendorAdapter jpaVendorAdapterTest() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(true);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
#Bean(name = "entityManagerFactoryTest")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryTest() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(this.dataSourceTest());
lef.setJpaProperties(this.hibernatePropertiesTest());
lef.setJpaVendorAdapter(this.jpaVendorAdapterTest());
lef.setPackagesToScan(new String[] { "our.dcollect.model"});
return lef;
}
}
The Unit Test class abbriviated for legibility:
package our.dcollect.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import our.dcollect.configuration.AppConfiguration;
import our.dcollect.configuration.HibernateConfigurationTest;
import our.dcollect.model.OpenIC;
import our.dcollect.repository.OpenICRepository;
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {AppConfiguration.class, HibernateConfigurationTest.class})
public class OpenPositionsServiceTest {
#Autowired
private OpenICRepository OpenICDAO;
#PersistenceContext(unitName = "entityManagerFactoryTest")
private EntityManager entityManager;
#Test
#Transactional(value="transactionManagerTest", propagation = Propagation.REQUIRES_NEW)
public void testOIC() {
System.out.println("getOpenPositionsNotRegisteredInPushBanch");
OpenIC oic = new OpenIC();
oic.setBaId("111");
oic.setBezeichnung("abc");
// clear the persistence context so we don't return the previously cached location object
// this is a test only thing and normally doesn't need to be done in prod code
entityManager.clear();
OpenICDAO.saveAndFlush(oic);
List<OpenIC> list = OpenICDAO.findAll();
assertEquals(list.size(), 1);
OpenIC oicReadBack = list.get(0);
OpenICDAO.delete(oicReadBack.getOpenICId());
}
[...]
}
Steps Towards the Solution:
The posts from Funtik helped a lot. The following setps I carried out:
#DependsOn("transactionManagerTest") to tell Spring that the
EntityManagerFactory needs to be loaded after the TransactionManager
but it did not solve the problem.
Introducing #Profile("test") for HibernateConfigurationTest and #Profile("!test") for HibernateConfiguration. On the test
class I put #ActiveProfiles("test"). This separated the beans;
only one flavour was loaded during the test: the ones in
HibernateConfigurationTest. This however did not solve the
problem either.
Then I completely removed one profile in a separate branch to see whether the two configuration for the DB cause the issue. I
experienced the same problem with one DB configuration as before.
I added #TestExecutionListeners({TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class}) to the unit test
class and #Rollback(false) to the test method to see whether
anything is saved in the MySQL database. I also changed
"hibernate.hbm2ddl.auto" to "create", to preserve the DB after the
test. It changed the situation as the message appeared in the log:
"[...] Began transaction (1) for test context
[DefaultTestContext#a15b73 [...]". So one transaction context has
definitely been created and has had 1 transaction. The problem was
however that the entity was not persisted in the database if I call
OpenICDAO.save(oic) in the test. In addition, calling
OpenICDAO.saveAndFlush(oic) causes the nearly the exception below:
"[...] 4671 [main] WARN org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener#45c9b3] to process 'after' execution for test: method [public void our.dcollect.service.OpenPositionsServiceTest.testGetOpenPositionsNotRegisteredInPushBanch()], instance [our.dcollect.service.OpenPositionsServiceTest#dc7b7d], exception [org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress]
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only [...]"
Tests in error:
testOIC(our.dcollect.service.OpenPositionsServiceTest): no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
testOIC(our.dcollect.service.OpenPositionsServiceTest): Transaction rolled back because it has been marked as rollback-only
Tests run: 3, Failures: 0, Errors: 2, Skipped: 0
However, I only have 2 methods not 3 from which testOIC is reported twice.
Solution:
The transactionManager must be a PlatformTransactionManager hosting a JpaTransactionManager. This solved the problem. Thank you for all the comments. I found the #Profile annotation very useful and the idea of listing the beans in the application context. After having the correct transactionManager, the annotation DependsOn() caused a circular reference, so I removed it; #TestExecutionListeners annotation is also not necessary in this case. I took a simple demo application that I changed to my configuration and tried to reproduce the original fault. After being able to reproduce it, I checked the differences between the good and bad state, it helped to find the difference. (The same also needs to be done for transactionManagerTest that expects a SessionFactoryTest object.)
// #Bean(name="transactionManager")
// #Autowired
// public HibernateTransactionManager transactionManager(#Qualifier("sessionFactory") SessionFactory s) {
// HibernateTransactionManager txManager = new HibernateTransactionManager();
// txManager.setSessionFactory(s);
// return txManager;
// }
#Bean(name="transactionManager")
#Autowired
public PlatformTransactionManager transactionManager(#Qualifier("sessionFactory") SessionFactory s) {
return new JpaTransactionManager( entityManagerFactory().getObject() );
}
I had the same problem. From what I experienced it seems that the entityManager bean is loaded before transactionManager bean, so the spring does not sense the presence of any transactions at all.
#DependsOn annotation fixed this issue for me. Try setting the explicit dependency on TransactionManager like this:
#DependsOn("transactionManagerTest")
#Bean(name = "entityManagerFactoryTest")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryTest() {
I added the Solution to the original post at the bottom.
I have run into this issue while trying to persist an entity during test.
And followed your solution in trying to resolve:
"The transactionManager must be a PlatformTransactionManager hosting a JpaTransactionManager"
Changed HibernateTransactionManager to JpaTransactionManager
#Bean
public JpaTransactionManager transactionManager(EntityManagerFactory s) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(s);
return txManager;
}
Was very amazed for your solution to work. If anyone could point me on documentation where it's described it would be great.
Thank you.

Resources