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
Related
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.
I am working on a Spring application that has already set up a transaction manager.
In a configuration class it has already set up an entity manager reading from a persistence.xml and then sets up a JpaTransactionManager.
I am required to create a Spring Batch implementation and the problem is that, as I have found out from different posts, when using the #EnableBatchProcessing annotation it seems that a second transaction manager is registered and I cannot persist data inside my tasklets.
Is it possible to use two transaction managers or configure my application in a way that I will be able to persist my data?
Can you please provide me with sample code?
Thanks in advance.
EDIT:
This is the application config class, which already exists in the application:
#Configuration
#ComponentScan({
...
})
#EnableJpaRepositories("...")
#EnableTransactionManagement
#EnableJpaAuditing
#Import({SecurityConfig.class})
#PropertySource("classpath:application.properties")
public class ApplicationConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setPersistenceXmlLocation("classpath:/META-INF/persistence.xml");
return factory;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
this is my batch config:
#Configuration
#EnableBatchProcessing
public class BatchConfig {
#Autowired
private JobBuilderFactory jobs;
#Autowired
private StepBuilderFactory steps;
#Autowired
#Qualifier("entityManagerFactory")
private LocalEntityManagerFactoryBean batchEntityManagerFactory;
}
from which I am getting an:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.orm.jpa.LocalEntityManagerFactoryBean com.xxx.xxx.xxx.configuration.BatchConfig.batchEntityManagerFactory; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.orm.jpa.LocalEntityManagerFactoryBean] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.sp
ringframework.beans.factory.annotation.Qualifier(value=entityManagerFactory)}
EDIT 2:
This is what I have done:
#EnableJpaRepositories("xxx")
#Configuration
#EnableBatchProcessing
#PropertySource("classpath:application.properties")
public class BatchConfig {
#Autowired
private JobBuilderFactory jobs;
#Autowired
private StepBuilderFactory steps;
#Autowired
private ReportReaderProcessor reportReaderProcessor;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setPersistenceXmlLocation("classpath:/META-INF/persistence.xml");
return factory;
}
#Bean
public BatchConfigurer batchConfigurer() {
return new DefaultBatchConfigurer() {
#Override
public PlatformTransactionManager getTransactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return jpaTransactionManager;
}
};
}
#Bean
public JobRepository jobRepository() throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
factory.setTransactionManager(batchConfigurer().getTransactionManager());
return (JobRepository) factory.getObject();
}
#Bean
public SimpleJobLauncher simpleJobLauncher() throws Exception {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(jobRepository());
return simpleJobLauncher;
}
#Bean
public Step readReports() {
return steps
.get("readReports")
.tasklet(reportReaderProcessor)
.build();
}
#Bean
public Job reportJob() {
return jobs
.get("submitReportJob")
.start(readReports())
.build();
}
}
but now I am getting an other error:
15:47:23,657 ERROR [stderr] (pool-36-thread-1) org.springframework.transaction.InvalidIsolationLevelException: DefaultJpaDialect does not support custom isolation levels due to limitations in standard JPA. Specific arrangements may be implemented in custom JpaDialect variants.
There is an open issue for this case here: https://jira.spring.io/browse/BATCH-2294 which is fixed in version 4.1.0.M3. To use a custom transaction manager, you need to provide a BatchConfigurer in your application context, for example:
#Bean
public BatchConfigurer batchConfigurer() {
return new DefaultBatchConfigurer() {
#Override
public PlatformTransactionManager getTransactionManager() {
return new MyTransactionManager();
}
};
}
I am new to Spring and I tried to make an application based on this tutorial: http://websystique.com/spring/spring4-hibernate4-mysql-maven-integration-example-using-annotations. I've seen some similar questions but I couldn't figure it out, I still get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'RESTController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public service.UserService controller.RESTController.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=userService)}
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public service.UserService controller.RESTController.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=userService)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=userService)}
Here is the configuration class:
#Configuration
#EnableTransactionManagement
#ComponentScan({ "configuration" })
#PropertySource(value = { "classpath:database.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "model" });
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"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
The controller:
#RestController
public class RESTController {
#Autowired
#Qualifier("userService")
public UserService userService;
#RequestMapping(value = "/allGrades", method = RequestMethod.GET)
public ResponseEntity<List<Grade>> listAllGrades() {
List<Grade> grades = userService.getAllGrades();
if(grades.isEmpty()){
return new ResponseEntity<List<Grade>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Grade>>(grades, HttpStatus.OK);
}
This is the service:
#Service("userService")
#Transactional
public class UserServiceImp implements UserService{
private static final AtomicLong counterGrades = new AtomicLong();
private static final AtomicLong counterStudents = new AtomicLong();
private static List<Grade> grades;
private static List<Student> students;
#Autowired
private StudentDAO studentDAO;
#Autowired
private GradeDAO gradeDAO;
public UserServiceImp() {
}
public void saveGrade(Grade grade) {
gradeDAO.saveGrade(grade);
}
public List<Grade> getAllGrades() {
return gradeDAO.getAllGrades();
}
and the servlet-servlet.xml configuration file:
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="controller, dao, model, service, main, configuration">
</context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler />
<tx:annotation-driven />
Thanks a lot for help!
The #Controller requires the UserService to perform it's work. It is being #Autowired, but also with a #Qualifier("userService"). In this example I would not have used the #Qualifier because there are no other conflicting implementations of the UserService interface (just UserServiceImp). That said, the #Service has been defined with "userService" so the #Autowired with the #Qualifier should work. I can't explain why it is not for you, but suspect it has to do with how #Transactional is proxied.
In short, remove the #Qualifier("userService") line and #Autowired should work fine (Autowiring should be matched by UserService.
If that doesn't work, try moving the #Transactional annotation down from the class to the two methods in the class
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"
Here's my scenario. My project is using Spring (3.2.3.RELEASE), Struts2 (2.3.14.3) and JPA (2.0). We have a project (let's call it project A) that contains various entities and common classes. We use project A to generate a .jar file so that other projects can use these classes. In project A we've used the Spring stereotypes: #Component. #Service or #Repository for those classes we want Spring to inject. Whenever we try to inject beans from the jar, we get an error similar to:
No qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Could not autowire field: private com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Error creating bean with name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private
com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Unable to instantiate Action, com.ceiwc.ma.mvc.action.LoginAction, defined for 'doLogin' in namespace '/Login'Error creating bean with
name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private
com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
We are using Java configuration for Spring. Here is our configuration class:
package com.zzz.bc.config;
#Configuration
#ImportResource({"/WEB-INF/spring/spring-config.xml"})
#ComponentScan(basePackages = "com.zzz")
public class ApplicationConfig {
#Bean
public JavaMailSender mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(${app.mail.host});
return mailSender;
}
}
package com.zzz.bc.config;
#Configuration
#EnableTransactionManagement
#Import(ApplicationConfig.class)
#PropertySource({"classpath:db.properties"})
public class DataConfig {
#Autowired
Environment environment;
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
String[] packagesToScan =
{environment.getProperty("db.packagesToScan1"), environment.getProperty("db.packagesToScan2")};
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPackagesToScan(packagesToScan);
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("db.driver"));
dataSource.setUrl(environment.getProperty("db.url"));
dataSource.setUsername(environment.getProperty("db.username"));
dataSource.setPassword(environment.getProperty("db.password"));
return dataSource;
}
#Bean
public JpaVendorAdapter vendorAdapter() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setDatabase(Database.ORACLE);
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
We have #ComponentScan set to check to bean in the package of com.zzz. In project B, we have a Struts2 Action that we want to inject a bean from project A. Here is a snippet of the class from project B:
#SuppressWarnings("rawtypes")
#Service("CommonSQLService")
public class CommonSQLServiceImpl implements CommonSQLService {
#Autowired
CommonSQLDao cdao;
#Override
public Policy getPolicyById(String policyNo) {
return cdao.getPolicyById(policyNo);
}
#Override
public Policy getPolicy(Policy parmRec) {
return cdao.getPolicy(parmRec);
}
#Override
public ArrayList<Policy> getPolicies(String policyNo) {
return cdao.getPolicies(policyNo);
}
#Override
public List<Policy> getPolicies(Policy parmRec){
return cdao.getPolicies(parmRec);
}
}
Here is our action (removed getters/setters):
package com.zzz.ma.mvc.action;
#SuppressWarnings("serial")
#Component
#Scope("prototype")
#Namespace("/Login")
public class LoginAction extends ActionParent {
#Autowired
private IUserService userService; //Contained in project B
#Autowired
private CommonSQLService commonSQLService; //What's autowired from project A
private User user;
private String updateFlag;
private Integer parentMenuId;
private IwifWebNavmenuItem record;
public static final String LOGIN_STR = "login";
#Action(value = "doLogin", results = { #Result(name = "success", location = "/pages/login.jsp") })
public String login() {
updateFlag = "Y";
return SUCCESS;
}
#Action(value = "validate", results = {
#Result(name = "success", location = "/BrowseOptions/showOptions", type = "redirect"),
#Result(name = "login", location = "/pages/login.jsp") })
public String validateUser() {
if (updateFlag == null) {
session.remove(LOGIN_STR);
return LOGIN;
}
if (userService.validateUser(user.getUsername(), user.getPassword()) == null) {
addActionError(getText("invalid.user"));
return LOGIN;
}
session.put(LOGIN_STR, user.getUsername());
return SUCCESS;
}
#Action(value = "logout", results = { #Result(name = "success", location = "/pages/login.jsp") })
public String logout() {
updateFlag = StringUtils.EMPTY;
session.invalidate();
return SUCCESS;
}
}
Whenever we try to do this autowire, we get an error like the one listed above. What are we missing? Can't classes contained in a jar file with Spring Stereotypes be autowired?
Thanks for you help in advance!
Change #Service("CommonSQLService") to #Service("commonSQLService") or you can just use #Service if you're not implementing the CommonSQLService interface anywhere else.