Unable to inject bean with #Qualifier - spring

I have a use case where I am creating two different thread pool with executor service. One has previously existed and I am creating a new.
We have a Java configuration file where all beans are defined. I have created named beans (#Bean (name = "ExecutorService") and #Bean (name = "ExecutorServiceEx")) like following:
package com.amazon.procurementservice.spring;
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn;
import com.amazon.procurementservice.util.OpenPOItemsUtil; import com.amazon.procurementservice.util.POHeadersUtil; import com.amazon.procurementservice.util.POItemsUtil; import com.amazon.procurementviews.accesors.DynamoDBAccessor; import com.amazon.procurementviews.repositories.OpenPOItemRepository; import com.amazon.procurementviews.repositories.POHeaderRepository; import com.amazon.procurementviews.repositories.POItemRepository; import com.amazon.procurementviews.repositories.dynamodb.DynamoDBOpenPOItemRepository; import com.amazon.procurementviews.repositories.dynamodb.DynamoDBPOHeaderRepository; import com.amazon.procurementviews.repositories.dynamodb.DynamoDBPOItemRepository; import com.amazon.procurementviews.spring.ProcurementViewCommonConfig; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import amazon.odin.awsauth.OdinAWSCredentialsProvider;
#Configuration
#DependsOn("EnvironmentHelper")
public class ProcurementViewDynamoDbConfig extends ProcurementViewCommonConfig {
#Value("${ProcurementService.ProcurementSecondaryViews.DynamoDB.materialName}")
private String materialNameViews;
#Value("${ProcurementService.ProcurementSecondaryViews.DynamoDB.awsRegion}")
private String awsRegionViews;
#Value("${ProcurementService.DynamoDB.getPurchaseOrderItems.threadCount}")
private int threadCount;
#Value("${ProcurementService.DynamoDB.getPurchaseOrderItemExs.threadCount}")
private int threadCountEx;
/**
* Beans for repositories
*/
#Bean
POHeaderRepository poHeaderRepository() {
return new DynamoDBPOHeaderRepository(secondaryViewsViewAccessor(), fnSkuListS3Handler());
}
#Bean
POItemRepository poItemRepository() {
return new DynamoDBPOItemRepository(secondaryViewsViewAccessor());
}
#Bean
OpenPOItemRepository openPoItemRepository() {
return new DynamoDBOpenPOItemRepository(secondaryViewsViewAccessor());
}
#Bean
DynamoDBAccessor secondaryViewsViewAccessor() {
return new DynamoDBAccessor(secondaryViewsDynamoDBClient(), secondaryViewsDynamoDBMapper());
}
#Bean
DynamoDBMapper secondaryViewsDynamoDBMapper() {
return new DynamoDBMapper(secondaryViewsDynamoDBClient());
}
#Bean
AmazonDynamoDB secondaryViewsDynamoDBClient() {
final AmazonDynamoDB client =
AmazonDynamoDBClientBuilder.standard().withCredentials(new OdinAWSCredentialsProvider(materialNameViews)).withRegion(awsRegionViews).build();
return client;
}
#Bean(name = "ExecutorService")
ExecutorService threadPool() {
return Executors.newFixedThreadPool(threadCount);
}
#Bean(name = "ExecutorServiceEx")
ExecutorService threadPoolEx() {
return Executors.newFixedThreadPool(threadCountEx);
}
#Bean
POItemsUtil poItemsUtil() {
return new POItemsUtil(poItemRepository(), threadPool());
}
#Bean
OpenPOItemsUtil openPOItemsUtil() {
return new OpenPOItemsUtil(openPoItemRepository(), threadPool());
}
#Bean
POHeadersUtil poHeadersUtil() {
return new POHeadersUtil(poHeaderRepository(), threadPool());
}
}
And I am using them in another file with #Autowired and #Qualifier like the following :
#Autowired
#Qualifier("ExecutorServiceEx")
private final ExecutorService executorServiceEx;
But I am getting exception like following :
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.amazon.procurementservice.activities.GetPurchaseOrderItemExsActivity': Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.util.concurrent.ExecutorService' available: expected single matching bean but found 2: ExecutorService,ExecutorServiceEx
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.3.20.RELEASE.jar:4.3.20.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) ~[spring-beans-4.3.20.RELEASE.jar:4.3.20.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1198) ~[spring-beans-4.3.20.RELEASE.jar:4.3.20.RELEASE]
I tried with #Resource, but result is same. I also tried to add <context:annotation-config/> in application-config.xml but no luck
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans classpath:org/springframework/beans/factory/xml/spring-beans-4.0.xsd
http://www.springframework.org/schema/util classpath:org/springframework/beans/factory/xml/spring-util-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<!-- The main application context spring configuration -->
<import resource="application/environment.xml" />
<import resource="application/http-server.xml" />
<import resource="application/coral-throttle.xml" />
<import resource="application/service-chain.xml" />
<import resource="common/health-check.xml" />
<import resource="common/hibernate.xml" />
<import resource="common/dao-definitions.xml" />
<import resource="application/hibernate.xml" />
<import resource="common/procurement-infrastructure.xml" />
<import resource="common/procurement-common.xml" />
<!--
Add any beans specific to your application here
-->
<bean class="com.amazon.procurementservice.spring.AuditHistoryConfig" />
<bean class="com.amazon.procurementservice.spring.OpenPOItemConfig" />
<bean class="com.amazon.procurementservice.spring.ProcurementViewDynamoDbConfig" />
<bean class="com.amazon.procurementservice.spring.ProcurementViewElasticSearchConfig" />
<bean class="com.amazon.procurementservice.spring.AmazonProfilingConfig" />
<bean class="com.amazon.procurementservice.spring.MetricsConfig" />
<bean class="com.amazon.procurementservice.spring.POServiceConfig" />
<bean class="com.amazon.procurementservice.spring.ApplicationBean" />
</beans>
Please help identify and fix this issue.

Related

How to catch Spring bean creation error - Injection of autowired dependency?

AdminService.java
package service;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import dao.IAdminDAO;
import dao.IMemberDAO;
public interface AdminService
{
public HashMap<String, Object> adminLogin(String id,String pw);
}
AdminServiceImple.java
package service;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import dao.IAdminDAO;
#Service
public class AdminServiceImple implements AdminService
{
#Autowired
private IAdminDAO adminDao;
#Override
public HashMap<String, Object> adminLogin(String id, String pw)
{
HashMap<String, Object> adminResult = adminDao.selectOne(id);
if(adminResult != null)
{
String opwd = (String) adminResult.get("pw");
if(opwd.equals(pw))
{
if(adminResult.get("authority").equals(true))
{
return adminResult;
}
else
{
return null;
}
}
else
{
return null;
}
}
else
{
return null;
}
}
}
AdminController.java
package controller;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import service.AdminService;
import service.AdminServiceImple;
import service.MemberService;
#Controller
public class AdminController
{
#Autowired
public AdminServiceImple adminService;
// 관리자 로그인 폼 페이지
#RequestMapping("admin.do")
public String adminLoginPage()
{
return "adminLoginPage";
}
// 관리자 로그인했을 시 요청
#RequestMapping("adminLoginOK.do")
#ResponseBody
public String adminMainPage(#RequestParam(required=false) String id, #RequestParam(required=false)String pw,HttpSession session,HttpServletRequest req,HttpServletResponse resp)
{
HashMap<String, Object> adminLoginIdentify = adminService.adminLogin(id, pw);
if(adminLoginIdentify != null)
{
return "1";
}
else
{
return "0";
}
}
#RequestMapping("adminPage.do")
public String adminPage(HttpSession session,HttpServletRequest resquest,HttpServletResponse response) throws IOException
{
return "adminMainPage";
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:component-scan base-package="dao, service" />
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<property value="com.mysql.jdbc.Driver" name="driverClassName"></property>
<property value="jdbc:mysql://localhost/rachelvf" name="url"></property>
<property value="root" name="username"/>
<property value="mysql" name="password"/>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="mapperLocations" value="classpath:dao/mapper/*.xml"></property>
<property name="typeAliasesPackage" value="model"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="memberDao">
<property name="mapperInterface" value="dao.IMemberDAO"></property>
<property name="sqlSessionFactory" ref="SqlSessionFactory"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="adminDao">
<property name="mapperInterface" value="dao.IAdminDAO"></property>
<property name="sqlSessionFactory" ref="SqlSessionFactory"></property>
</bean>
</beans>
that is error code.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminServiceImple': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dao.IAdminDAO service.AdminServiceImple.adminDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [dao.IAdminDAO] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
I thought about the cause of the error, but I think it is because I did not insert the service annotation.
However, there is no typos in any way, and everything is written correctly and errors occur. Is there something I don't know?
Can you tell me what caused this error?
And what about the solution?
make sure that AdminDao bean is creating and injecting correctly into
AdminServiceImple
use this tag in your spring-cfg.xml file
<context:component-scan base-package="dao" />
and also scan the controller class using --
<context:component-scan base-package="controller" />
you have to give information of class which are going to use annotation to IOC container to create bean...
A mapper is registered to Spring by including a MapperFactoryBean in your XML config file like follows:
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
try this to scan your Service Package and Dao Package.
<context:component-scan base-package="dao, service" />
above code will scan the dao and service package respectively.

#Qualifier annotation not working

I am trying DI with autowiring and I came across #Qualifier annotation annd tried the following code:
Car.java
package beans;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Qualifier;
public class Car {
#Autowired
#Qualifier("e1")
private Engine engine;
// no need to have setter or constructor
public void showData(){
System.out.println("Engine Model Year : "+engine.getModelyear());
}
}
Engine.java
package beans;
public class Engine {
private String modelyear;
public void setModelyear(String modelyear) {
this.modelyear = modelyear;
}
public String getModelyear() {
return modelyear;
}
}
Spring.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- activate autowire annotation -->
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="e1" class="beans.Engine">
<property name="modelyear" value="2017"/>
</bean>
<bean id="e2" class="beans.Engine">
<property name="modelyear" value="2018"/>
</bean>
<bean id="c" class="beans.Car">
</bean>
</beans>
Main.java
package MainClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import beans.Car;
public class AutoAnno_Main {
public static void main(String[] args) {
ApplicationContext ap=new ClassPathXmlApplicationContext("resources/spring.xml");
Car c=(Car)ap.getBean("c");
c.showData();
}
}
And the error I am getting is:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'beans.Engine' available: expected single matching bean but found 2: e1,e2
what's wrong in this I think the syntax is correct is there any problem with version
I am using eclipse Oxygen
You just need to add <context:annotation-config /> in your spring.xml. Certain spring annotations are not activated unless this is added. In your case, spring is not reading the #Qualifier annotation without the <context:annotation-config />.
I have tested by adding this and it seems to work.
Update:
Your spring xml needs to have the spring schema for that to detect <context:annotation-config>. Your final xml looks like this.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- activate autowire annotation -->
<context:annotation-config />
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
<bean id="e1" class="beans.Engine">
<property name="modelyear" value="2017"/>
</bean>
<bean id="e2" class="beans.Engine">
<property name="modelyear" value="2018"/>
</bean>
<bean id="c" class="beans.Car">
</bean>
</beans>

#Autowired - No qualifying bean of type found for dependency at least 1 bean

Currently I'm facing an issue in Autowire configuration between controller and the service layer.
I'm unable to trace my mistakes.
Simple Log Info
SEVERE: Exception while loading the app
SEVERE: Undeployment failed for context /OTT
SEVERE: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.ott.service.EmployeeService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Below I have also given the Controller and Service Layer code and also the dispatcher-servlet.xml
Controller
package com.ott.controller;
import com.ott.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
* #author SPAR
*/
#Controller
public class AdminController {
private EmployeeService employeeService;
#RequestMapping("/employee")
public String employee(){
this.employeeService.fetchAll();
return "employee";
}
#Autowired(required = true)
#Qualifier(value="employeeService")
public void setEmployeeService(EmployeeService empService) {
this.employeeService = empService;
}
}
Service Interface
package com.ott.service;
import com.ott.hibernate.Employee;
import java.util.List;
/**
*
* #author SPAR
*/
public interface EmployeeService {
List<Employee> fetchAll();
}
Service Interface Impl
package com.ott.service;
import com.ott.dao.EmployeeDAO;
import com.ott.hibernate.Employee;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
*
* #author SPAR
*/
#Service
public class EmployeeServiceImpl implements EmployeeService{
private EmployeeDAO employeeDAO;
#Override
#Transactional(readOnly = true)
public List<Employee> fetchAll() {
List<Employee> employees = employeeDAO.fetchAll();
for (Employee employee : employees) {
System.out.println("Name : "+employee.getFirst_Name() +" "+ employee.getLast_Name());
System.out.println("Email Id : "+employee.getEmail_Id());
}
return employees;
}
#Autowired(required = true)
#Qualifier(value="employeeDAO")
public void setEmployeeDAO(EmployeeDAO empDAO) {
this.employeeDAO = empDAO;
}
}
Dispatcher-servlet.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="com.ott.controller"/>
<context:component-scan base-package="com.ott.hibernate"/>
<context:component-scan base-package="com.ott.service"/>
<context:component-scan base-package="com.ott.dao"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles-def/general-layout.xml</value>
</list>
</property>
</bean>
<bean id="viewResolverTiles" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
</bean>
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
Guys I found the issue
I just tried by adding the qualifier name in employee service finally it solved my issue.
#Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService{
}
You don't have to necessarily provide name and Qualifier. If you set a name, that's the name with which the bean is registered in the context. If you don't provide a name for your service it will be registered as uncapitalized non-qualified class name based on BeanNameGenerator. So in your case the Implementation will be registered as employeeServiceImpl. So if you try to autowire with that name, it should resolve directly.
private EmployeeService employeeServiceImpl;
#RequestMapping("/employee")
public String employee() {
this.employeeService.fetchAll();
return "employee";
}
#Autowired(required = true)
public void setEmployeeService(EmployeeService employeeServiceImpl) {
this.employeeServiceImpl = employeeServiceImpl;
}
#Qualifier is used in case if there are more than one bean exists of same type and you want to autowire different implementation beans for various purposes.
I believe for #Service you have to add qualifier name like below :
#Service("employeeService") should solve your issue
or after #Service you should add #Qualifier annontion like below :
#Service
#Qualifier("employeeService")
In your controller class, just add #ComponentScan("package") annotation. In my case the package name is com.shoppingcart.So i wrote the code as #ComponentScan("com.shoppingcart") and it worked for me.
You forgot #Service annotation in your service class.
#Service: It tells that particular class is a Service to the client. Service class contains mainly business Logic. If you have more Service classes in a package than provide #Qualifier otherwise it should not require #Qualifier.
Case 1:
#Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService{
}
Case2:
#Service
public class EmployeeServiceImpl implements EmployeeService{
}
both cases are working...
If you only have one bean of type EmployeeService, and the interface EmployeeService does not have other implementations, you can simply put "#Service" before the EmployeeServiceImpl and "#Autowire" before the setter method.
Otherwise, you should name the special bean like #Service("myspecial") and put "#autowire #Qualifier("myspecial") before the setter method.
Just add below annotation with qualifier name of service in service Implementation class:
#Service("employeeService")
#Transactional
public class EmployeeServiceImpl implements EmployeeService{
}
Missing the 'implements' keyword in the impl classes might also be the issue

Autowiring Controller doesn't work after adding entityManagerFactory bean

I've wrote a spring mvc webserver which uses NEO4j as data backend. Now i want to expand this with cassandra, so the server should be able to use both databases.
I have followed these 2 tutorials on how to combine Kundera (A JPA based Cassandra API):
https://github.com/impetus-opensource/Kundera/wiki/Using-Kundera-with-Spring
https://code.google.com/p/kundera/wiki/HowToUseKunderaWithSpring
But i'm not able to add the entitymanagerfactory bean to my applicationcontext.xml file.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="cassandra_pu"/>
</bean>
When i do this, spring gives an error that it can not create any of the already existing controllers that my webserver uses.
Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'indexController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private bmsapp.service.DataBasePopulator bmsapp.controller.IndexController.dbPopulator; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] for bean with name 'entityManagerFactory' defined in class path resource [applicationContext.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4797)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5291)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private bmsapp.service.DataBasePopulator bmsapp.controller.IndexController.dbPopulator; nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] for bean with name 'entityManagerFactory' defined in class path resource [applicationContext.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 22 more
Those controllers are created by using the #Controller annotation in their class files and by autowiring them in the files where they are used. This works fine normally but when i add the entityManagerFactory bean it suddenly stops working. How is this possible?
My applicationContext file currently looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
">
<!-- Scans the classpath for annotated components that will be auto-registered
as Spring beans. For example #Controller and #Service. -->
<context:component-scan base-package="bmsapp" />
<!-- Activate Spring Data Neo4j repository support -->
<neo4j:config storeDirectory="data/graph.db" base-package="bmsapp.domain" />
<neo4j:repositories base-package="bmsapp.repository" />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="cassandra_pu"/>
</bean>
<tx:annotation-driven mode="proxy" />
<!-- context:annotation-config / -->
<!-- use this for Spring Jackson JSON support -->
<mvc:annotation-driven />
And my persistence.xml file:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="cassandra_pu">
<provider>com.impetus.kundera.KunderaPersistence</provider>
<properties>
<property name="kundera.nodes" value="localhost"/>
<property name="kundera.port" value="9160"/>
<property name="kundera.keyspace" value="KunderaExamples"/>
<property name="kundera.dialect" value="cassandra"/>
<property name="kundera.client.lookup.class" value="com.impetus.client.cassandra.pelops.PelopsClientFactory" />
<property name="kundera.cache.provider.class" value="com.impetus.kundera.cache.ehcache.EhCacheProvider"/>
<property name="kundera.cache.config.resource" value="/ehcache-test.xml"/>
</properties>
</persistence-unit>
SimpleComment domain class:
package bmsapp.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "SIMPLE_COMMENT", schema = "KunderaExamples#cassandra_pu")
#XmlRootElement(name = "SimpleComment")
public class SimpleComment {
#Id
#Column(name = "COMMENT_ID")
private int id;
#Column(name = "USER_NAME")
private String userName;
#Column(name = "COMMENT_TEXT")
private String commentText;
public SimpleComment() {
}
public SimpleComment(int commentId, String userName, String commentText) {
this.id = commentId;
this.userName = userName;
this.commentText = commentText;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCommentText() {
return commentText;
}
public void setCommentText(String commentText) {
this.commentText = commentText;
}
}
SpringExampleDao:
package bmsapp.repository;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import bmsapp.domain.SimpleComment;
#Service
public class SpringExampleDao
{
#PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager entityManager;
public SimpleComment addComment(int id, String userName, String commentText)
{
SimpleComment simpleComment = new SimpleComment(id, userName, commentText);
entityManager.persist(simpleComment);
return simpleComment;
}
public SimpleComment getCommentById(String Id)
{
SimpleComment simpleComment = entityManager.find(SimpleComment.class, Id);
return simpleComment;
}
public List<SimpleComment> getAllComments()
{
Query query = entityManager.createQuery("SELECT c from SimpleComment c");
List<SimpleComment> list = query.getResultList();
return list;
}
}
The relevant part of the stacktrace is:
nested exception is java.lang.ClassNotFoundException: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
So you need to add a dependency to spring-orm, see http://mvnrepository.com/artifact/org.springframework/spring-orm.
However, I'm not sure that really solves your problem. In the description you're mentioning Neo4j and I cannot see what part of your description relates to that.

Spring Autowire JdbcDaoSupport

I'm receiving the an error when trying to autowire a class that extends JdbcDaoSupport. I have my DAO classes and Controller classes separated into 2 different spring contexts. DAO classes are in the root context and the Controller classes are in the servlet context. I've set up the component-scanning so that there is no overlap in beans between the 2 contexts (is that the correct pattern?). All these factors combined with the fact that my DAOs extend JdbcDaoSupport seems to be causing the issue, and I don't understand why. I'm just learning spring so I don't fully understand all the concepts yet.
EDIT: This behavior seems to be caused by the fact that JdbcDaoSupport/DaoSupport implements the InitializingBean interface. Still confused though.
Here is the error I am receiving:
Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.test.dao.CustomerDAO2 org.test.servlet.HomeController.customerDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.test.dao.CustomerDAO2] 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)}
Here are my files:
HomeController.java
package org.test.servlet;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.test.dao.*;
#Controller
public class HomeController
{
#Autowired
CustomerDAO2 customerDAO;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model)
{
model.addAttribute("customer", customerDAO.getCustomer());
return "home";
}
}
CustomerDAO2.java
package org.test.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.*;
import org.test.dto.Customer;
#Repository
public class CustomerDAO2 extends JdbcDaoSupport
{
public CustomerDAO2()
{
}
#Autowired
public CustomerDAO2(DataSource datasource)
{
this.setDataSource(datasource);
}
#Transactional
public Customer getCustomer()
{
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource());
Customer customer = jdbcTemplate.queryForObject("select * from customer", new CustomerMapper());
return customer;
}
public static class CustomerMapper implements RowMapper<Customer>
{
public Customer mapRow(ResultSet rs, int rowNum) throws SQLException
{
Customer customer = new Customer();
customer.setCustomerId(rs.getInt("customerId"));
customer.setCustomerNumber(rs.getString("customerNumber"));
return customer;
}
}
}
application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scans within the base package of the application for #Components to configure as beans -->
<!-- #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="org.test">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<!-- Enables the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/crm?user=root&password=password" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scans within the base package of the application for #Components to configure as beans -->
<!-- #Controller, #Service, #Configuration, etc. -->
<context:component-scan base-package="org.test.servlet"/>
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
I found my answer in this post:
Spring expected at least 1 bean which qualifies as autowire candidate for this dependency
Basically, I need to create an interface for my DAO classes. Something like this:
public interface ICustomerDAO {
Customer getCustomer();
}
Note: it would probably be better to make a more generic CRUD interface.
Then you use the interface type for dependency injection instead of using the class type:
#Autowired
ICustomerDAO customerDAO;
The reason this is necessary is because Spring creates underlying proxy classes:
http://insufficientinformation.blogspot.com/2007/12/spring-dynamic-proxies-vs-cglib-proxies.html
http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying

Resources