I am trying to build extensible application, that uses lot of generics. So far I have code:
#Component
#Named
#Scope("session")
#Repository
public interface FrameworkRepository<E extends FrameworkEntity>
extends PagingAndSortingRepository<E, Long> {
}
#Component
#Named
#Scope("session")
#Repository
public interface OrderRepository extends FrameworkRepository<Order> {
}
#Component
#Named
#Scope("session")
public class FrameworkService<R extends FrameworkRepository> implements Serializable {
#Autowired
private R repository;
}
#Component
#Named
#Scope("session")
public class OrderService extends FrameworkService<OrderRepository> {
public OrderService() {
}
}
However, when I am trying to use OrderService instance in facelets page, there is exception with the message:
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [...FrameworkRepository]
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 guess, that the root problem can be my use of generics. Maybe Spring Data (repositories) can not automaticall create class from the OrderRepository interface, or maybe Spring #Autowired can not find the instance (created by Spring Data on the fly) of OrderRepository and autowire it into generic field.
I know that in any time I can find workarounds without use of generics, but that involves much unnecesary code. Generics can lead to more concise code.
I use Hibernate 4.x, Spring 4.x, JPA 2.1.
I had to add
<jpa:repositories base-package="dk.nmc.imarket.data"
entity-manager-factory-ref="entityManagerFactory">
</jpa:repositories>
in my applicationContext.xml and I remode unnecesary annotations from the repositories - they are just repositories and not the full Spring beans by name and for session. It helped so far.
Related
I have a MyService class which has repository field supposed to be injected.
public class MyService {
#Autowired
private MyRepository repository;
// ...ommited
}
And there is MyRepository interface only implemented by MyRepositoryImpl class with #Mapper annotation of MyBatis.
public interface MyRepository {
// ...ommited
}
#Mapper
public interface MyRepositoryImpl extends MyRepository {
// ...ommited
}
When I try to start SpringBootApplication, NoUniqueBeanDefinitionException is thrown.
#SpringBootApplication(nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class)
#MapperScan(nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class)
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
(...omitted)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'com.example.MyService':
Unsatisfied dependency expressed through field 'repository';
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'com.example.MyRepository' available:
expected single matching bean but found 2: com.example.MyRepositoryImpl,com.example.MyRepository
(...omitted)
Why is MyRepository interface registered as one of bean even though it doesn't have #Component annotation nor isn't included any bean configurations?
And I found that everything work fine if I don't use FullyQualifiedAnnotationBeanNameGenerator as nameGenerator.
Any ideas?
There can be many other ways to mark an interface as a bean. Some of them are:
#RepositoryDefinition above MyRepository interface
MyRepository extends CrudRepository or JpaRepository
Check if any of these exist.
Update 1:-
The problem seems to be in #MapperScan. What it does is scans for all the interfaces in a package and register them as bean; and if I am not wrong MyRepository and MyRepositoryImpl are in the same package. That's the reason why 2 beans are being created with names com.example.MyRepositoryImpl, com.example.MyRepository and basically both are of same type as MyRepositoryImpl extends MyRepository.
Now when you are using #Autowired on repository field of MyService, it gets confused as in which one to inject. To resolve this the easiest approach is to use #Primary over MyRepositoy which will give that interface a priority while injecting. Another approach is to use #Qualifier("uniqueName") over both the interfaces and also above repository field of MyService along with #Autowired specifying which one you want to inject. You can visit official documentation from here to learn more.Hope this helps a bit .
Spring is not able to figure out the bean whose class is supposed to be implementing the Repository interface.
Put the annotation #Repository above the RepositoryImpl Class. It will find it.
In Spring, is it possible to avoid a NoUniqueBeanDefinitionException in the following scenario:
My application references beans in a 3rd party library
appBean="thirdPartyClass"
The bean code is in a 3rd party library I can't edit
#Component
public class ThirdPartyClass {
#Autowired
private ThirdPartyInterface thirdPartyInterface;
The third party interface is used by two classes I do control
This class:
public class MyClass1 implements ThirdPartyInterface {
and this class:
public class MyClass2 implements ThirdPartyInterface {
Currently, NoUniqueBeanDefinitionException is occurring when I try to start my application saying the following:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'thirdPartyClass': Unsatisfied dependency expressed through field 'thirdPartyIntereface'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'ThirdPartyInterface' available: expected single matching bean but found 2: MyClass1,MyClass2
Considering you cannot change the ThirdPartyClass class.
Make one of the implemented classes as #Primary to be considered as the primary bean to be Autowired in the ThirdPartyClass class.
#Primary
#Component
public class MyClass1 implements ThirdPartyInterface {
}
And add #Qualifier to the other implemented class. And use that same qualifier in your other classes to Autowire and use it seamlessly.
#Component
#Qualifier("queue2")
public class MyClass2 implements ThirdPartyInterface {
}
#Component
public class MyOtherClass {
#Autowired
#Qualifier("queue2")
private ThirdPartyInterface thirdPartyInterface;
}
The error clearly says what the problem is -
When you have 2 class implementing same interface and you are trying to use #Autowired via the interface, Spring does not know which implementation to pick (MyClass1 or MyClass2).
You need to be specific. Use #Qualifier to specify which implementation to pick.
I quickly found one example here - Spring #Autowired and #Qualifier
I'm trying to understand why I can't autowire a class repository but I can autowire a interface repository in the same package for the same test. The same repository works as expected when I start the application.
First, the error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.app.person.repository.PersonRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.raiseNoMatchingBeanFound(DefaultPersonbleBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.doResolveDependency(DefaultPersonbleBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultPersonbleBeanFactory.resolveDependency(DefaultPersonbleBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 28 more
I have a very simple example. The test:
#RunWith(SpringRunner.class)
#DataJpaTest
public class PersonRepositoryTest {
#Autowired
private PersonRepository personRepository; // fail...
#Autowired
private PersonCrudRepository personCrudRepository; // works!
#Test
public void findOne() {
}
}
The repository class:
#Repository
public class PersonRepository {
//code
}
The repository interface:
#Repository
public interface PersonCrudRepository extends CrudRepository<Person, Long> {
}
After a bad experience with this same error, I'm trying to find some detail in my configuration or test what is responsible for this problem. Another possibility is the #DataJpaTest does not have support for class repositories.
I think I was right about the problem. After find a post on Github and read the Spring Documentation:
#DataJpaTest can be used if you want to test JPA applications. By
default it will configure an in-memory embedded database, scan for
#Entity classes and configure Spring Data JPA repositories. Regular
#Component beans will not be loaded into the ApplicationContext.
My PersonRepository is considered a regular #Component, because it is not a Spring Data JPA repository (the interface is). So, it is not loaded.
The alternative solution is to use #SpringBootTest instead of #DataJpaTest.
The disadvantage with this solution is that will load all your context while running your test and, with this, disabling the test slicing. But do the job.
Another option, still using #DataJpaTest, is include a #Repository filter annotation, like this:
#DataJpaTest(includeFilters = #ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Repository.class))
Just another alternative might be #Import as shown here https://stackoverflow.com/a/41084739/384674.
I am having an issue with autowiring a bean property in my class declared as a #Component. I've tried a number of different things, but unfortunately I am getting a NoSuchBeanDefinitionException during spring configuration for this particular bean.
Below is a some example code, to model what I have currently.
package com.foo.bar;
#Component
public class MyDeployer implements ApplicationContextAware
{
#Autowired
private ClusterRegistry clusterRegistry; //The bean I am trying to wire
...
}
In my application context, I have the following:
<beans ...... />
<context:component-scan base-package="com.foo.bar" />
<context:annotation-config />
<bean id="clusterRegistry" name="clusterRegistry" class="com.my.implementation.ClusterRegistryFileImpl" />
</beans>
My ClusterRegistryFileImpl class is defined below:
package com.my.implementation;
public final class ClusterRegistryFileImpl implements ClusterRegistry
{
...
}
Note that the ClusterRegistryFileImpl implements the ClusterRegistry interface, and this interface/implementation class has no dependencies. These files also are not using component scan (and are not annotated by #Component, but I wouldn't think they'd need to be if I'm declaring the bean in my appContext.
My integration test looks like
#ContextConfiguration(locations= {
"/com/app/context/path/appContext.xml",
"/com/app/context/path/aDifferentAppContext.xml"
})
public class MyDeployerTest extends AbstractTestNGSpringContextTests
{
#Autowired
private MyDeployer deployer; //class that uses the bean I need
#Test
protected void testDeployerStartup()
{
deployer.startup();
...
}
}
Below is the error:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.my.implementation.ClusterRegistry] 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)}
Any suggestions or direction would be much appreciated.
Your class
ClusterRegistryFileImpl
should has an annotation ( like #Service if is a service class, or #Repository or #Component).
And i am not sure if the final accessor applies.
I have an interface as show below
public interface UserManager {
void insertUser(User user);
.......
Now I have an implementation class as below
#Service
public class UserManagerImpl implements UserManager {
#Autowired
private UserDAO userDAO;
In my controller
#Controller
public class ExampleGizmoController {
#Autowired
private UserManager userManager;
UserDAOImpl is
#Service
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
My application-context.xml
<context:annotation-config/>
<context:component-scan base-package="com.foo" />
which scans all my packages.I have deployed it as war file and when the deployment happens,
The userManager property is not getting autowired to the ExampleGizmoController and shows the error in tomcat as below
Spring-MVC threw load() exception: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.foo.UserManager] 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 was able to make out that autowiring was not happening , even though it was annotation driven and component scanning is turned on. Is there anything else I should do for autowiring to work ?
<mvc:annotation-driven/>
is also required in your config file
Maybe it's stupid... but try to remove implements UserManager from UserManager Impl ..
You should use #Service("userManager"). Its a way of telling Spring that you want to name your UserManagerImpl bean instance with "userManager".
Same error i faced, but i've got one more dao class which retrieves information of user manager. You should add #Repository annotation to dao class.
Your another dao class looks like that;
#Repository("userManagerDao")
public class UserManagerDAOImpl implements UserManagerDao{
public UserManagerDTO createNewUserManager() {
UserManagerDTO userManager = new UserManagerDTO();
userManager.setId(1);
userManager.setFirstName("First Name");
userManager.setLastName("Last Name");
return userManager;
}
}