Spring and Spring Data JPA are not working in conjunction - spring

I am using Spring Data JPA (1.3.0.RELEASE) with Spring (3.2.2.RELEASE ) in one project and facing a weird problem. I am using xml based configuration as mentioned below.
<context:annotation-config/>
<context:component-scan base-package="x.y.z.services"/>
Using this configuration to scan the classes decorated with #Component, #Service and #Named annotations.
<jpa:repositories base-package="x.y.z.repo"/>
Using this configuration to scan all interfaces extending JpaRepository. These interfaces are injected in Service classes in the following way.
#Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
#Inject
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public List<User> listUsers() {
return userRepository.findAll();
}
}
This configuration works as expected without any issue. But when I add the following configuration I get the BeanCreationException for UserRepository.
<bean id="securityRealm" class="x.y.z.Realm">
<property name="userService">
<bean class="x.y.z.services.UserServiceImpl"/>
</property>
</bean>
And, here is the Java code for Realm and UserRepository.
public class Realm extends AuthorizingRealm implements IRealm {
private UserService userService;
#Inject
public void setUserService(UserService userService) {
this.userService = userService;
}
#Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
return null;
}
}
public interface UserRepository extends JpaRepository<User, String> {
}
As per above configuration, Spring is able to create the bean for userService but not able to create the UserRepository bean.
I can get this error away by scanning x.y.z.Realm and decorating it with #Service annotation. But it will be a very big constraint and design issue to my application.
AFAICT, Spring is not able to create the bean for UserRepository as it's implementation class is not available and has to be provided by jpa:repositories configuration. I can see that Spring and Spring Data JPA are not working in conjunction.
Can somebody please help me to solve this problem. Below is stacktrace of the exeception.
2013-04-30 21:44:04.745:INFO:/web:Initializing Spring root WebApplicationContext
2013-04-30 21:44:07,009 [ERROR] [main] [org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shiroFilter' defined in class path resource [META-INF/Test-web/security-config.xml]: Cannot resolve reference to bean 'securityManager' while setting bean property 'securityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testShiroRealm': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: x.y.z.core.service.UserService x.y.z.core.security.testShiroRealm.userService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void x.y.z.core.service.internal.UserServiceImpl.setUserRepository(x.y.z.repo.UserRepository); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [x.y.z.repo.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1134)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.AbstractApplicationContext.registerBeantesttProcessors(AbstractApplicationContext.java:753)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.eclipse.jetty.server.handler.ContextHandler.callContextInitialized(ContextHandler.java:764)
at org.eclipse.jetty.servlet.ServletContextHandler.callContextInitialized(ServletContextHandler.java:406)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:756)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:242)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1221)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:699)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:454)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:90)
at org.eclipse.jetty.server.Server.doStart(Server.java:263)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
at runjettyrun.Bootstrap.main(Bootstrap.java:80)
... 34 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void x.y.z.core.service.UserServiceImpl.setUserRepository(x.y.z.repo.UserRepository); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [x.y.z.repo.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:601)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
... 45 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [x.y.z.repo.UserRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:986)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:856)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:558)
... 47 more

This was the bug in Spring Data JPA and has been fixed. Please have a look at JIRA issue for resolution.
https://jira.springsource.org/browse/DATAJPA-335

Related

NoBean found exception

**I am getting below error even though i have down the #autowired .please some one let me know why this issue happening its a ant build with spring config
utor.
2022-07-08 10:18:09,856 WARN org.springframework.context.support.
ClassPathXmlApplicationContext - Exception encountered during context initialization
cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'delegateProcessor':
Unsatisfied dependency expressed through field 'headerProcessor';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean found for dependency
[org.springframework.batch.item.ItemProcessor<com.abc.proj.model.FileHeader,
com.abc.proj.model.FileHeader>]:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=headerProcessor)}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'delegateProcessor': Unsatisfied dependency expressed
through field 'headerProcessor';
nested exception is org.springframework.beans.factory.
NoSuchBeanDefinitionException: No qualifying bean found for dependency
[org.springframework.batch.item.ItemProcessor<com.abc.proj.model.FileHeader,
com.abc.proj.model.FileHeader>]: expected at least 1 bean which qualifies as
autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=headerProcessor)}
#Component
public class DelegateProcessor implements ItemProcessor<Object, Object>, InitializingBean {
#Autowired
#Qualifier("headerProcessor")
private ItemProcessor<FileHeader, FileHeader> headerProcessor;
#Autowired
#Qualifier("detailProcessor")
private ItemProcessor<FileDetail, FileDetail> detailProcessor;
#Autowired
#Qualifier("trailerProcessor")
private ItemProcessor<FileTrailer, FileTrailer> trailerProcessor;
#Component
public class HeaderProcessor implements ItemProcessor<Object, Object>{
#Autowired
private HeaderValidatorDao headerValidatorDao ;**
With a configuration class you could initialize your beans manually, specially if they need custom names.
#Configuration
public class MyCustomConfiguration {
#Bean(name ="headerProcessor")
public ItemProcessor<FileHeader, FileHeader> headerProcessorBean() {
ItemProcessor<FileHeader, FileHeader> myBean = new HeaderProcessor<>();
//Do whaterever you need to initilize your bean
return myBean;
}
#Bean(name ="detailProcessor")
public ItemProcessor<FileDetail, FileDetail> detailProcessorBean() {
ItemProcessor<FileDetail, FileDetail> myBean = new ItemProcessor<>();
//Do whaterever you need to initilize your bean
return myBean;
}
}
In this way these beans will be available for autowiring.

How to autowire a service and a repository together

I have to fix the following error. Anyone can help
SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'searchController': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire method: public void
com.website.dev.controller.SearchController.setRecordingService(com.website.dev.service.RecordingService);
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.website.dev.service.RecordingService]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations: {}
#Controller
public class SearchController {
private RecordingService recordingService;
#Autowired
public void setRecordingService(RecordingService recordingService) {
this.recordingService = recordingService;
}
#RequestMapping("/search")
public String showSearch(){
return "search";
}
}
#Service("recordingService")
public interface RecordingService {
//methods
}
public class RecordingServiceImpl implements RecordingService {
#Autowired
private RecordingRepository recordingRepository;
//methods that use recordingRepository
}
public interface RecordingRepository {
}
#Repository
public class RecordingJpaRepository implements RecordingRepository {
#PersistenceContext
private EntityManager entityManager;
//methods that use entityManager
}
service-context.xml
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="com.website.dev.service">
</context:component-scan>
</beans>
website-servlet.xml
<context:component-scan
base-package="com.website.dev.controller"> // searchcontroller is in this package
</context:component-scan>
web.xml
<context:component-scan
base-package="com.enepath.dev.controller">
</context:component-scan>
EDIT
If I autowire RecordingServiceImpl I get the following
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'recordingServiceImpl': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.website.dev.repository.RecordingRepository
com.website.dev.service.RecordingServiceImpl.recordingRepository;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.website.dev.repository.RecordingRepository] 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)}
I added the following configuration in service-context.xml and this solved my issue
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="com.website.dev.service">
</context:component-scan>
<context:component-scan
base-package="com.website.dev.repository">
</context:component-scan>
<context:component-scan
base-package="com.website.dev.repository.jpa">
</context:component-scan>
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.website.dev.service.RecordingService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
If we look above exception, we will find that spring container is unable to create or instantiate the bean of type com.website.dev.service.RecordingService.
It is because POJO class is not managed by spring container.
#Autowire annotation will work only those objects which are managed by spring (ie created by the spring container).
you should annotate the RecordingServiceImpl class as Service
#Service
public class RecordingServiceImpl implements RecordingService
and remove #Service("recordingService") from
public interface RecordingService {
//methods
}
RecordingServiceImpl would be managed by Spring container and spring would be able to create the bean.

Failed to load ApplicationContext in JUnit with JNDI datasource

I have some troubles testing my application, whereas it works well in normal execution.
I think it comes from JNDI resources which are not found, but I don't understand why and how to fix it.
When I start my Junit test, I got this error:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DAOImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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=myDatasource)}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDatasource' defined in URL [file:src/test/resources/spring/test-dao-config.xml]: Invocation of init method failed; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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=myDatasource)}
at ...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] 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=myDatasource)}
at ..
Here is my configuration:
Context.xml
<Resource name="jdbc/myDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#database:99999:instance"
username="user"
password="password"
validationQuery="select 1 from dual"
testOnBorrow ="true"
maxActive="5"
maxIdle="1"
maxWait="-1" />
test-dao-config.xml
<bean id="myDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDatasource" />
</bean>
DaoImpl
#Repository
public class DacsDAOImpl implements DacsDAO
{
private final static Logger LOGGER = LoggerFactory.getLogger(DAOImpl.class);
#Autowired
#Qualifier("myDatasource")
private DataSource myDatasource;
....
}
And my tests
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:src/test/resources/spring/test-dao-config.xml" })
public class MyDAOImplTest
{
private MyDAO dao;
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
// builder.bind("java:comp/env/jdbc/myDatasource", "myDatasource");
// builder.activate();
}
#Before
public void setUp() throws IllegalStateException, NamingException
{
dao = new MyDAOImpl();
}
#Test
public void testTotalUser()
{
int result = dao.getTotalUser();
Assert.assertEquals(0, result);
}
}
Thanks
You are running in a test case so everything in your Context.xml isn't available as that is only available on tomcat. Why do you need a jndi lookup in your test case anyway? If you want to test your dao use an in-memory database like hsql, h2 or derby and use that instead. Spring has some nice tags to make it easy for you.
<jdbc:embedded-database id="myDataSource" type="H2">
// Add some init scripts here.
</jdbc:embedded-database>
If you really need to do a JNDI lookup you are almost there in your test case. However you have to register a DataSource not a String. So you still will need to construct some (in-memory) datasource and bind that to the mock jndi location
#BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// Construct in-memory database
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/myDatasource", myDatasource); //Actual datasource not a String!
builder.activate();
}
And finally your test is also flawed, you are loading your context but aren't doing anything with it. You are constructing a MyDAOImpl in your #Before method. Why even bother loading the context as you are doing nothing with.

'Could not autowire field' exception in Spring

I have a Spring application and am using Spring version 3.0.4.
When I start the server it shows me an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.domain.Custom org.controller.CustomController.custom; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.domain.Custom] 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:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
Code for the domain class
#Entity
#Configurable
#Table(name="tbltest")
public class Custom implements Serializable{
#Autowired
public transient CustomRepository customRepository;
public static CustomRepository getRepository() {
CustomRepository repository = new Custom().CustomRepository;
return repository;
}
#Transactional(readOnly = true)
public static Custom find(final Long id) {
return getRepository().find(id);
}
}
Included configurations in application context
<context:load-time-weaver/>
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="org.domain.custom"/>
Code for my test class:
#Test
#Transactional
public void testCreateNew() {
Custom registration = new Custom("ttt");
Custom.find(1l);
registration.persist();
Assert.assertEquals(true, registration.getId() > 0);
}
Controller
#Controller
#RequestMapping("/custom")
public class CustomController
{
#Autowired
public Custom Custom;
}
And I have added spring-instrument.jar for the VM argument.
Looks like you forgot to add
<context:component-scan base-package="org.domain" />
to your application-context.xml so that spring knows where to scan for your #Component annotations. Just enabling <context:annotation-config /> is not enough.

Spring error when trying to manage several classes that share a common base class?

Im currently using Spring 3.0.x ..
Im wondering what's wrong with these structures,
where i would like to manage the subclasses but not the parent classes.
I have 2 child DAOs extending the BaseDAO :
public abstract class BaseDAO<K, E> {
....
}
#Repository
public class UserDAO extends BaseDAO<String, User> {
....
}
#Repository
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
And i have the services like this, with hierarchies like this :
public abstract class BaseService<K, E extends BaseEntity, D extends BaseDAO<K, E>> {
#Autowired
protected D dao;
....
}
public abstract class BaseCommonService<K, E extends BaseCommonEntity, D extends BaseDAO<K, E>> extends BaseService<K,E,D> {
....
}
#Service
public class UserService extends BaseCommonService<String, User, UserDAO> {
....
}
When trying to inject the userservice object to my application, it throws error like this :
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'testEntities': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private
com.primetech.module.common.service.UserService
com.primetech.module.purchase.app.TestEntities.userService;
nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:574)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at
org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:93)
at
com.primetech.module.purchase.app.TestEntities.main(TestEntities.java:81)
Caused by:
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private
com.primetech.module.common.service.UserService
com.primetech.module.purchase.app.TestEntities.userService;
nested exception is
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:507)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
... 13 more Caused by:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'userService': Injection of autowired
dependencies failed; nested exception
is
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:838)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:780)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:697)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 15 more Caused by:
org.springframework.beans.factory.BeanCreationException:
Could not autowire field: protected
com.primetech.core.parent.BaseDAO
com.primetech.core.parent.BaseService.dao;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:507)
at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:283)
... 26 more Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type
[com.primetech.core.parent.BaseDAO] is
defined: expected single matching bean
but found 2: [userDAO, approvalDAO]
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:790)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:697)
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 28 more
I tried changing this section, removing the #Repository annotation :
#Repository
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
into this :
public class ApprovalDAO extends BaseDAO<String, Approval> {
....
}
And things run without error, but then, the approvalDAO isnt managed by the spring anymore, and cannot be injected later by #Autowired
Any suggestions on how i can solve this problem ?
Autowiring works only if there is exactly one implementation bean of the specific type present in the Spring Context. I'd assume that using the generic D extends BaseDao leads to a situation where Spring is trying to autowire instances of BaseDao instead of UserDao and ApprovalDao. Because you both UserDao and ApprovalDao implement BaseDao, Spring context contains multiple implementations of BaseDao and cannot decide which one should be used.
Spring is trying to tell this to you in the stack trace
org.springframework.beans.factory.NoSuchBeanDefinitionException:
__No unique bean of type__ [com.primetech.core.parent.BaseDAO] is defined:
expected single matching bean but found 2: [userDAO, approvalDAO]
You could try to test this by defining the dao in the concrete service using the actual dao type e.g.
public abstract class BaseService<K, E extends BaseEntity, D extends BaseDAO<K, E>> {
private final D dao;
protected BaseService(D dao) {
this.dao = dao;
}
}
public class UserService extends BaseService<K, User, UserDao<K, User>> {
#Autowired
public UserService(UserDao dao) {
super(dao);
}
}
I'd continue by defining interfaces for UserDao and ApprovalDao so that dependencies are on interfaces and not implementations. The daos may still have a common super interface and their implementations may be based on the BaseDao to avoid unnecessary duplication.
In the example I've defined the injected Dao in the constructor because I assume that the same dao instance should be used throughout the lifetime of the service and the service cannot exist without the dao set. In my opinion, a constructor argument communicates this contract better. Furthermore it might make the class a bit more testable and maintainable.

Resources