I'm trying to autowire an interface inside a controller bean
In my context configuration file I've put
<context:annotation-config />
and
<bean id="viewVerbale" class="com.sirfe.controller.VerbaliController" />
my controller class is
#Controller
public class VerbaliController {
#Autowired
VerbaliRepository repository;
private static final Logger logger = LoggerFactory.getLogger(VerbaliController.class);
#RequestMapping(value = "/sirfe/verbale/{sequVerbale:.+}", method = RequestMethod.GET)
public ModelAndView viewVerbale(#PathVariable("sequVerbale") String sequVerbale) {
logger.debug("welcome() - sequVerbale {}", sequVerbale);
Verbali verbale = repository.findOne(Long.parseLong(sequVerbale));
ModelAndView model = new ModelAndView();
model.setViewName("sirfe/verbali/viewVerbale");
model.addObject("sequVerbale", sequVerbale);
return model;
}
}
my interface signature is
public interface VerbaliRepository extends CrudRepository<Verbali, Long> { }
and when I launch my app I get
Could not autowire field: com.sirfe.repository.VerbaliRepository com.sirfe.controller.VerbaliController.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sirfe.repository.VerbaliRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Looks like you're trying to use Spring JPA repository.
In order to have Spring create bean for your repository interfaces, you need in applicationContext.xml to declare what package to scan
<jpa:repositories base-package="com.sirfe.repository" />
Doing so, Spring will generate bean implementing the interface for you.
See Spring JPA Repositories
Spring is complaining that it cannot find a valid bean definition that matches, ie there is no bean defined that is an implementation of VerbaliRepository.
You need to define a bean or alternatively annotate an implementation class with #Component eg
<bean id="myRepository" class="com.foo.bar.MyRepository" />
or
#Component
public class MyRepository implements VerbaliRepository {
....
}
Related
Repository class:
package ru.spb.repository.user;
#Repository
public class AnketUserRepository implements UserRepository {
#Autowired
private CrudUserRepository crudRepository;
}
Interface:
package ru.spb.repository;
public interface UserRepository {
}
Service:
package ru.spb.service;
#Service
public class UserService {
private final UserRepository repository;
#Autowired
public UserService (UserRepository repository){
this.repository = repository;
}
}
Configs:
in spring-app.xml:
<context:component-scan base-package="ru.spb.service"/>
in spring-db.xml:
<context:component-scan base-package="ru.spb.repository.user"/>
But I catch the following exception:
NoSuchBeanDefinitionException: No qualifying bean of type 'ru.spb.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I tried to add #Repository on UserRepository-interface, but without success.
You need to Annotate the Interface also
package ru.spb.repository;
#Repository
public interface UserRepository {
}
Your component scan is configured only to the package of the implementing class, but you are autowiring the interface which is on a different (non component scanned) package.
Move the #Repository annotation to the inteface, and add ru.spb.repository to your component-scan
I moved
<context:component-scan base-package="ru.spb.repository.user"/>
from spring-db.xml to spring-app.xml. And this problem is solved.
However I dont understand the reason of this problem.
I have a Spring component defined like this:
#Component
public class SearchIndexImpl implements SearchIndex {
IndexUpdater indexUpdater;
#Autowired
public SearchIndexImpl(final IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
}
along with two implementations of the IndexUpdater interface, like:
#Component
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
#Component
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
If I try to auto-wire SearchIndexImpl like this:
#Autowired
private SearchIndex searchIndex;
I get the following exception:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'IndexUpdater' available: expected single matching bean but found 2: indexDirectUpdater,indexQueueUpdater
which is expected since Spring cannot tell which IndexUpdater implementation to auto-wire for the indexUpdater parameter in the constructor of SearchIndexImpl. How do I guide Spring to the bean that it should use? I understand I can use the #Qualifier annotation, but that will hard-code the index updater to one of the implementation, while I want the user to be able to specify what index updater to use. In XML, I can do something like:
<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl">
<constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>
How do I do the same using Spring's Java annotations?
Use the #Qualifier annotation to specify the dependency to use :
public SearchIndexImpl(#Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
Note that #Autowired is not needed to autowire the arg constructor of a bean since Spring 4.
To answer to your comment.
To let the class that will use the bean to define the dependency to use you could allow it to define the IndexUpdater instance to inject in the container such as :
// #Component not required any longer
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
// #Component not required any longer
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
Declare the bean in a #Configuration class :
#Configuration
public class MyConfiguration{
#Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
The SearchIndexImpl bean will now resolve the dependency thanks to IndexUpdater getIndexUpdater().
Here we use #Component for one bean and #Bean for its dependency.
But we could also allow a full control on the beans to instantiate by using only #Bean and by removing #Component on the 3 classes :
#Configuration
public class MyConfiguration{
#Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
#Bean
public SearchIndexImpl getSearchIndexFoo(){
return new SearchIndexImpl(getIndexUpdater());
}
I'm trying to implement Spring AOP in multiple layers application and make advice for #Service and #Controller classes.
Everything works fine without aspect class. When I add that part of code it causes Spring configuration problem.
#Aspect class:
#Aspect
#Component
public class ApplicationMonitor {
private static final Logger logger = Logger.getLogger(ApplicationMonitor.class);
#Pointcut(value = "execution(* hr.mycompany.controller.impl.MyCompanyController.update(*)) && args(obj)")
public void updateMC(Object obj){}
#Before(value="updateMC(obj)")
public void beforeUpdateMC(JoinPoint jp, Object obj) {
Object obj = jp.getArgs()[0];
logger.info("beforeUpdateMC " + obj);
}
}
Spring XML aspect configuration:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Application #Controller and #Service classes:
#Controller
public class MyCompanyController implements IMyCompanyController{
#Autowired
private IMyComapnyService myCompanyService;
}
#Service
public class MyCompanyService implements IMyComapnyService {
#Autowired
private IGenericHibernateDao<Object, Integer> vwObjectDao;
}
Error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hr.mycompany.dao.IGenericHibernateDao] 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)}
09:11:27,871 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/BasicData-portlet]] (http--0.0.0.0-8083-2) StandardWrapper.Throwable: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyCompanyService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private hr.mycompany.dao.IGenericHibernateDao hr.mycompany.services.impl.MyCompanyService.vwObjectDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hr.mycompany.dao.IGenericHibernateDao] 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)}
Where the problem is?
EDIT:
Part of class with Hibernate methods:
#Transactional(readOnly = true)
public abstract class GenericHibernateDao<T, PK extends Serializable> implements IGenericHibernateDao<T, PK> {
private static final Logger log = LoggerFactory.getLogger(GenericHibernateDao.class);
#Autowired
#Qualifier(value = "hibernateSessionFactory")
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#SuppressWarnings("unchecked")
#Transactional(readOnly = false)
public PK save(T entity) {
Assert.notNull(entity, "Argument entity cannot be null in a call to GenericHibernateDao.save !");
Session session = getSessionFactory().getCurrentSession();
return (PK) session.save(entity);
}
...
}
EDIT (22-02-2019):
When I change this line of code:
<aop:aspectj-autoproxy proxy-target-class="true"/>
like this:
<aop:aspectj-autoproxy />
Error disapears, but aspect does not work.
I found solution.
I change this line of code in Spring XML config file:
<aop:aspectj-autoproxy proxy-target-class="true"/>
I set proxy-target-class to false:
<aop:aspectj-autoproxy proxy-target-class="false"/>
I deleted this dependency from pom.xml file:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
I set the same spring-aop vesion like Spring version I use in Spring XML config file.
I changed this:
http://www.springframework.org/schema/aop/spring-aop.xsd
like this:
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
I have an Amazon Lambda (springboot) that is deployed and works fine.
I inject services from external projects (dependency add to pom) this way:
#Bean
public SomeExternalService someExternalService() {
return new SomeExternalService;
}
I have to do this because when uploaded to Amazon, #Autowired doesn't work.
Now, from another springboot project (not lambda) I have this service that uses a DAO.
Service
#Service
public class StateService {
#Autowired
private StateRepository repository;
/**
* Find all {#code State}
*/
public void findSomething(String thing) {
return repository.findSomething("thing");
}
.....
Repository
#EnableScan
public interface StateRepository extends PagingAndSortingRepository<State, String> {
List<State> findSomething(String thing);
When building I get
Error creating bean with name 'StateService': Unsatisfied dependency
expressed through field 'repository'
and
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'mypackage.repository.StateRepository'
available: expected at least 1 bean which qualifies as autowire
candidate.
I inject that service exactly like the others
#Bean
public StateService stateService() {
return new StateService;
}
I can't do the same for StateRepository.
StateRepository class must have #Component annotation or add it in your #Configuration class as #Bean.
#Configuration
#ComponentScan("com.company")
public class ConfigClass {
// your #Bean's
#Bean
public StateRepository stateRepository() {
return new StateRepository();
}
// now can #Autowired
}
I'm using a SpringBeanAutowiringInterceptor in an EJB3 stateless session bean, as described in the Spring documentation.
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class) // Allows spring injection for its setter methods
public class MyClassImpl extends MyAbstractClass implements MyClass
{
....
#Autowired
public void setMyCustomService2(MyService svc) {
this.service = svc;
}
And in SpringConfig.xml:
<bean id="myCustomService1" class="...MyService"/>
<bean id="myCustomService2" class="...MyService"/>
When Spring tries to autowire this I get
No unique bean of type [...MyService ] is defined:
expected single matching bean but found 2: [myCustomService1 , myCustomService2]
Unfortunately, it seems EJB autowiring defaults to byType mode, and I can't find a way to change it to byName mode.
Is this possible, and if so, how?
Have you tried with a Qualifier?
#Autowired
#Qualifier("myCustomService1")
public void setMyCustomService2(MyService svc) {
this.service = svc;
}