Could not initialize class org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider - spring

I'm trying to learn Spring Data JPA and I'm getting the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in org.mql.gestionstages.config.PersistanceJPAConfig: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider
I have the following configuration class for JPA :
#Configuration
#EnableTransactionManagement
public class PersistanceJPAConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "mypackage.models" });
**JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();**
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DriverManagerDataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/gestion_stages");
dataSource.setUsername("root");
dataSource.setPassword("");
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL57Dialect");
return properties;
}
}
The exception is thrown in this line:
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
These are all the jars I have in my /WEB-INF/lib folder:
aspectjweaver-1.9.5.jar
hibernate-core-5.2.17.Final.jar
hibernate-entitymanager-5.2.17.Final.jar
hibernate-jpa-2.1-api-1.0.2.Final.jar
hibernate-jpamodelgen-5.2.17.Final.jar
javax.servlet.jsp.jstl-1.2.2.jar
javax.servlet.jsp.jstl-api-1.2.2.jar
mysql-connector-java-8.0.13.jar
org.eclipse.persistence.jpa-2.6.8.jar
spring-aop-5.2.2.RELEASE.jar
spring-aspects-5.2.2.RELEASE.jar
spring-beans-5.2.2.RELEASE.jar
spring-context-5.2.2.RELEASE.jar
spring-core-5.2.2.RELEASE.jar
spring-data-commons-2.2.2.RELEASE.jar
spring-data-jpa-2.2.2.RELEASE.jar
spring-expression-5.2.2.RELEASE.jar
spring-jcl-5.2.2.RELEASE.jar
spring-jdbc-5.2.2.RELEASE.jar
spring-orm-5.2.2.RELEASE.jar
spring-tx-5.2.2.RELEASE.jar
spring-web-5.2.2.RELEASE.jar
spring-webmvc-5.2.2.RELEASE.jar

The root exception is NoClassDefFoundError: Could not initialize class org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider which basically means you are missing a jar.
To gather all the required jars for an application is a PITA, I therefore strongly suggest to switch to a dependency management solution like Maven where you declare a dependency to Spring Data JPA and it gathers all the transient dependencies for you.

Related

Spring Boot Data - Getting 'Not a managed Type' error when the package is not included in default entityManager

My application has two entity managers (entityManagerFactory and entityManagerFactorySec). The default is associated with package 'com.abc.model' and the second one is associated with package 'com.abc.uw.model'.
What I observed is that the application startup is fine only if I include the second package as well to the default Entitymanager. Getting the following error even though I see from the logs that the repo got created.
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dmUwRefRulesRsltRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.abc.uw.model.DmUwRefRulesRslt
Java configs are
entityManagerFactory:
return builder.dataSource(dmDs).packages(new String[]{"com.abc.model"}).build();
//startup is fine only with the commented line below
//return builder.dataSource(dmDs).packages(new String[]{"com.abc.model","com.abc.uw.model"}).build();
entityManagerFactorySec:
return builder.dataSource(dataSource).packages(new String[]{
"com.abc.uw.model"}).persistenceUnit("alternate").build();
Could not find why it is not working when the package is included in the packages of the second entitymanager factory
I am providing the complete snippet for both the configs.
Config 1:
#Configuration
#PropertySource("classpath:application.yml")
#EnableJpaRepositories ( basePackages = "com.abc.pcs", entityManagerFactoryRef = "entityManagerFactory")
public class PersistenceConfig {
#Bean(name = "dmDs")
#ConfigurationProperties(prefix = "dm.datasource")
public FactoryBean dmJndiDataSource() {
return new JndiObjectFactoryBean();
}
#Bean("entityBuilder")
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
return new EntityManagerFactoryBuilder(hibernateJpaVendorAdapter,
new HashMap<String, Object>(){{put("eclipselink.weaving", "false");}}, null);
}
/**
* #param builder
* #param dmDs
* #return
* #link https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-use-two-entity-managers
*/
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory( EntityManagerFactoryBuilder builder, #Qualifier("dmDs") final DataSource dmDs) {
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = builder.dataSource(dmDs).packages(new String[]{"com.abc.model"}).build();
return localContainerEntityManagerFactoryBean;
}
#Bean("transactionManager")
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactory") final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Config 2:
#Configuration
#PropertySource("classpath:application.yml")
#EnableJpaRepositories ( basePackages = {"com.abc.clp.hnw","com.abc.uw"}, entityManagerFactoryRef = "entityManagerFactorySec")
public class AltPersistenceConfig {
#Bean(name = "dsSecondary")
#ConfigurationProperties(prefix = "ds_secondary.datasource")
public FactoryBean dmEclipseLinkJndiDataSource() {
return new JndiObjectFactoryBean();
}
#Bean(name="entityManagerFactorySec")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySec( EntityManagerFactoryBuilder builder, #Qualifier("dsSecondary") final DataSource dataSource) {
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = builder.dataSource(dataSource).packages(new String[]{
"com.abc.uw.model"}).persistenceUnit("alternate").build();
return localContainerEntityManagerFactoryBean;
}
#Bean("transactionManagerSec")
public PlatformTransactionManager transactionManagerEclipseLink(#Qualifier("entityManagerFactorySec") final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
I'm 99% sure that one way or the other you are referencing entities from the second package in the repository for the first one. Either directly or possibly through some attribute of an entity.

Could not autowire hibernate SessionFactory in dao class

i have a problem injecting a hibernate sessionfactory bean in my dao class. saying there is no bean qualified with that name
#Repository("emaildao")
public class EmailDAOImpl implements EmailDAO{
private SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory s){
sessionFactory = s;
}
#Override
public void saveMessages(List<Message> messages) {
// some code persisting messages
}
here is my config files
#Configuration
#EnableTransactionManagement
#ComponentScan({ "com.opm.emailheader" })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.opm.emailheader"} );
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.query_cache", environment.getRequiredProperty("hibernate.query_cache"));
properties.put("hibernate.query_cache_size", environment.getRequiredProperty("hibernate.query_cache_size"));
properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibarnate.hbm2ddl.auto"));
properties.put("hibernate.connection.CharSet","utf8");
properties.put("hibernate.connection.characterEncoding","utf8");
properties.put("hibernate.connection.useUnicode",true);
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
the code structure folder is like:
com.opm.emailheader
app
dao
daoimpl
conf
HibernateConfiguration.java
AppInitializer.java
WebConfig.java
SecurityConfig.java
the exception stack trace :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emaildao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.opm.emailheader.app.dao.daoimpl.EmailDAOImpl.setSessionFactory(org.hibernate.SessionFactory); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
project structure

Multiple SessionFactory configuration fails with org.springframework.beans.factory.UnsatisfiedDependencyException Exception

Our application need to deal with multiple databases. We tried to configure multiple data sources through Hibernate configuration and added two configurations one for database 1 and second for database 2. This configuration fails with following Exception
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DB1TransactionManager' defined in class path resource [org/npcc/ccms/config/db/HibernateConfig4DB1.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: AgrgtrSessionFactory,HRSessionFactory,StageSessionFactory; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 3: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
root cause
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
First Database Configuration:
#Configuration
#EnableTransactionManagement
#ComponentScan({ "org.npcc.ccms.config" })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB1 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB1.class);
#Autowired
private Environment environment;
#Bean(name="DB1SessionFactory")
public LocalSessionFactoryBean db1SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db1" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean(name="DB1TransactionManager")
#Autowired
#Qualifier("DB1SessionFactory")
public HibernateTransactionManager db1TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
Second database configuration:
#Configuration
#EnableTransactionManagement
#ComponentScan({ "org.npcc.ccms.config" })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB2 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB2.class);
#Autowired
private Environment environment;
#Bean(name="DB2SessionFactory")
public LocalSessionFactoryBean db2SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db2" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean(name="DB2TransactionManager")
#Autowired
#Qualifier("DB2SessionFactory")
public HibernateTransactionManager db2TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
That's because you defined 2 SessionFactory in your configuration and Spring can't guess which one to pick.
You could autowire your sessionFactory and use it in your #Bean :
#Autowired
#Qualifier("DB1SessionFactory")
private SessionFactory sessionFactory;
#Bean(name="DB1TransactionManager")
public HibernateTransactionManager db2TransactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(this.sessionFactory);
return txManager;
}
To explicitly choose the bean to use.
Moreover you should note that only one configuration need to hold #EnableTransactionManagement, plus you are component scanning twice the same package which is unnecessary. Again, you have 2 #PropertySource with the same properties file, only one will be needed.
In your case I would create a RootHibernateConfig holding #Configuration, #EnableTransactionManagement, #ComponentScan({ "org.npcc.ccms.config" }) and #PropertySource(value = { "classpath:application.properties" }) annotations + #Import with your HibernateConfig4DB1 and HibernateConfig4DB2.
You can remove #Autowired and #Qualifier annotations from your transactionManager beans methods. Don't forget to explicitly use the needed transactionManager in your code.
See : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html
Spring - Is it possible to use multiple transaction managers in the same application?
I faced the same problem . Solved like following way
#Bean(name = "rebootSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(
new String[]
{
"com.ra.reboot.b.persistence.entity",
"com.ra.reboot.bl.persistence.entity",
"com.ra.reboot.bla.persistence.entity",
"com.ra.reboot.blaBla.persistence.entity"
});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean(name="rebootTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "true");
hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
hibernateProperties.setProperty("hibernate.cache.use_query_cache", "true");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_prefix", "history");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", "_audit");
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "500");
return hibernateProperties;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
#Bean
public DataSource dataSource() {
Properties jdbcProperties = this.getJdbcPropertise();
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcProperties.getProperty("jdbc.drive.class"));
dataSource.setUrl(jdbcProperties.getProperty("jdbc.database.url"));
dataSource.setUsername(jdbcProperties.getProperty("jdbc.database.username"));
dataSource.setPassword(jdbcProperties.getProperty("jdbc.database.password"));
return dataSource;
}
private Properties getJdbcPropertise() {
InputStream inputStream = RarebootDataSourceConfig.class.getClassLoader().getResourceAsStream("dev.jdbc.properties");
Properties jdbcProperties = new Properties();
try {
jdbcProperties.load(inputStream);
} catch (NullPointerException IOException) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
} catch (IOException e) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
}
return jdbcProperties;
}
This is the config file. Then in the BaseDao
#Autowired
#Qualifier("rebootSessionFactory")
public SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public Session getSession() {
return this.sessionFactory.getCurrentSession();
}
In my Service
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional(value = "rebootTransactionManager")
public class ClientLeadInfoService {
...
}
Make sure you are using this :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
So I have 2 config file(Here I post only one example file). I have to tell my BaseDao which session factory I am using for which. In my service I have to tell which transaction manager I am using.
It was happening due to inheritance. there was class BaseClass (base class) and class DerrivedClass (extended from BaseClass). When I was using #Autowire annotation, it was giving out an error with reason there are 2 objects i.e. Class BaseClass and Class DerrivedClass.
I used #Resource annotation instead of #Autowire as below
#Resource(name="derrivedClass")
DerrivedClass testObj;
It seems Spring boot creates beans with names same as class in camel letter. e.g. if my class is TestClass then the bean name would be "testClass"

No transactional EntityManager available even though one is configured

I'm attempting to transactionally interact with my MySQL database through JPA and Spring data.
config
#Configuration
#EnableJpaRepositories("com.some.models.repositories")
#EnableTransactionManagement
public class MegabotsConfiguration {
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setJpaProperties(additionalProperties());
factory.setPackagesToScan(new String[] { "com.datarank.megabots.models.entities", "com.datarank.megabots.models.repositories" });
factory.setDataSource(dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/local_ttaggdb");
dataSource.setUsername( "root" );
dataSource.setPassword( "" );
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
//...
}
And here's where I'm attempting to use a transaction:
#Repository
#Scope("prototype")
#Transactional
public class BotWorkQueueRepository {
#Autowired
private BotWorkQueueJPARepository botWorkQueueJPARepository; //this is the jparepository referenced in the #EnableJpaRepositories in config
#PersistenceContext
private EntityManager entityManager;
#Transactional
public synchronized void flagInFlight(final List<BotWorkQueueEntity> botWorkQueueEntities) {
try {
//...set a few properties on entities, then
entityManager.flush(); //Exception thrown here
entityManager.clear();
} catch (Exception e) {
LOGGER.warn("Error making in flight: " + e);
}
}
}
The error I'm getting:
javax.persistence.TransactionRequiredException: No transactional EntityManager available
I've tried most of the solutions for this error posted in SO, with no success.
One thing for starter,
In maven, if you are using the appassembler-maven-plugin, add the following line to your plugin.configuration tag in the POM file.
<extraJvmArguments>-javaagent:"$REPO"/org/aspectj/aspectjweaver/1.8.5/aspectjweaver-1.8.5.jar</extraJvmArguments>
If you are running in an IDE add the following line to your VM arguments.
-javaagent:<PATH TO MAVEN REPO>/org/aspectj/aspectjweaver/1.8.5/aspectjweaver-1.8.5.jar
Where path to maven repo may look something like /User/kenny/.m2/repository/.
$REPO will be auto-resolved in the POM file.

BeanDefinitionStoreException exception since trying to switch app to javaconfig from xml config

I am running into some configuration issue since trying to switch to javaconfig from xml config.
Here is the problematic configuration class:
#Configuration
#EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
#Profile({ "default", "cloud" })
public class DataConfiguration {
#Value("${database.driverClassName}")
private String driverClassName;
#Value("${database.url}")
private String url;
#Value("${database.username}")
private String username;
#Value("${database.password}")
private String password;
#Value("${database.validationQuery}")
private String validationQuery;
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setTestOnBorrow(Boolean.TRUE);
dataSource.setTestOnReturn(Boolean.TRUE);
dataSource.setTestWhileIdle(Boolean.TRUE);
dataSource.setTimeBetweenEvictionRunsMillis(1800000);
dataSource.setNumTestsPerEvictionRun(3);
dataSource.setMinEvictableIdleTimeMillis(1800000);
dataSource.setValidationQuery(validationQuery);
dataSource.setMaxActive(5);
dataSource.setLogAbandoned(Boolean.TRUE);
dataSource.setRemoveAbandoned(Boolean.TRUE);
dataSource.setRemoveAbandonedTimeout(10);
return dataSource;
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
#Bean
public HibernateJpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
#Bean
public HibernatePersistence persistenceProvider() {
return new HibernatePersistence();
}
#Bean(name = "entityManagerFactory", destroyMethod = "close")
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setPackagesToScan("com.bignibou.domain");
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProvider(persistenceProvider());
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setJpaPropertyMap(propertiesMap());
return entityManagerFactoryBean.getObject();
}
public Map<String, String> propertiesMap() {
Map<String, String> propertiesMap = new HashMap<>();
propertiesMap.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
propertiesMap.put("hibernate.hbm2ddl.auto", "update");
propertiesMap.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
propertiesMap.put("hibernate.connection.charSet", "UTF-8");
propertiesMap.put("hibernate.show_sql", "true");
propertiesMap.put("hibernate.format_sql", "true");
propertiesMap.put("hibernate.use_sql_comments", "true");
return propertiesMap;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
Here is the exception I get:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public static javax.persistence.EntityManager org.springframework.orm.jpa.SharedEntityManagerCreator.createSharedEntityManager(javax.persistence.EntityManagerFactory)] threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:181)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:570)
... 121 more
Caused by: java.lang.NullPointerException
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.initProxyClassLoader(SharedEntityManagerCreator.java:151)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.<init>(SharedEntityManagerCreator.java:143)
at org.springframework.orm.jpa.SharedEntityManagerCreator.createSharedEntityManager(SharedEntityManagerCreator.java:118)
at org.springframework.orm.jpa.SharedEntityManagerCreator.createSharedEntityManager(SharedEntityManagerCreator.java:96)
at org.springframework.orm.jpa.SharedEntityManagerCreator.createSharedEntityManager(SharedEntityManagerCreator.java:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:160)
... 122 more
It seems there's an issue with the entityManagerFactory config... What I am getting wrong?
If you are not using the entityManagerFactory() method anywhere in your java configuration, you can instead return the LocalContainerEntityManagerFactoryBean object.
The LocalContainerEntityManagerFactoryBean is both an InitializingBean and a FactoryBean. These are special interfaces that Spring can use to initialize a bean and then add it to the context.
You could therefore change your method to
#Bean(name = "entityManagerFactory", destroyMethod = "close")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setPackagesToScan("com.bignibou.domain");
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProvider(persistenceProvider());
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter());
entityManagerFactoryBean.setJpaPropertyMap(propertiesMap());
return entityManagerFactoryBean;
}
Spring will take care of calling afterPropertiesSet() and getObject() on the object returned by the method and adding the created EntityManagerFactory bean to the context.
This is detailed in the IoC chapter of the Spring documentation.
adding the following line sorted the issue:
entityManagerFactoryBean.setJpaPropertyMap(propertiesMap());
entityManagerFactoryBean.afterPropertiesSet();//NOTICE HERE!!!
return entityManagerFactoryBean.getObject();

Resources