I have a main #SpringBootApplication which needs to scan a specific package in order to enable the JPA repositories, so I use #EnableJpaRepositories to specify that. Right now I'm implementing unit tests and I want to test the Controller component only, so I followed the tutorial in the official docs where they use #WebMvcTest(MyController.class) to test a controller with a service dependency.
The problem is that this is not working for me because it is trying to load the JpaRepositories that I specify in the main Spring Boot application (when I comment the #EnableJpaRepositories in the main class the test runs without problem).
I'm guessing I need to create a specific configuration for the test class so it can ignore the main configuration (since I only want to load the Controller and mock the service layer), but I don't know how to create such. I tried adding an empty configuration, but it is still failing with the same error:
#TestConfiguration
static class TestConfig {}
This is the error I get:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'failureTaskHandler': Unsatisfied dependency expressed through field 'myManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'msgManager': Unsatisfied dependency expressed through field 'inboundManager'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inboundManager': Unsatisfied dependency expressed through field 'messageRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageRepository' defined in com.example.MessageRepository defined in #EnableJpaRepositories declared on MonitorApplication: Cannot create inner bean '(inner bean)#45e639ee' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#45e639ee': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
And my test class:
#WebMvcTest(MyController.class)
public class MyControllerTest {
#Autowired private MockMvc mvc;
#MockBean private MyService service;
// Tests here
// #Test
// public void...
}
MyController class:
#RestController
#CrossOrigin
#RequestMapping("/api")
#Slf4j
public class MyController {
#Autowired private MyService service;
#PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody SearchResponse getOrders(#RequestBody SearchRequest orderSearchRequest) {
log.info("Receiving orders request...");
return service.getOrders(orderSearchRequest);
}
}
Quick solution
Remove #EnableJpaRepositories from your Spring Boot Application class. Use:
#SpringBootApplication
public class MainApplication {
}
in place of
#SpringBootApplication
#EnableJpaRepositories
public class MainApplication {
}
In this case Spring Boot will find Spring Data JPA on the classpath and uses auto-configuration to scan packages for the repositories.
Use #EnableJpaRepositories to scan a specific package
Use #NikolaiShevchenko solution (it is incorrect) with a separate configuration, but without explicit importing it, by #Import({ DataConfiguration.class }), (because tests will be explicitly import the configuration too) and let Spring Boot find your configuration during packages scan.
#SpringBootApplication
public class MainApplication {
}
#Configuration
#EnableJpaRepositories(basePackages = "com.app.entities")
public class JpaConfig {
}
Important
Don't forget to add basePackages property, if you put your configuration in a separate package.
Declare separate configuration
#Configuration
#EnableJpaRepositories
public class DataConfiguration { ... }
Import it into the application
#SpringBootApplication
#Import({ DataConfiguration.class })
public class MainApplication { ... }
but don't import into MyControllerTest
I've specified Qualifier on both autowired et bean method.
So What am i missing ?
#Configuration
#EnableWebSecurity
public class CustomSecurityCOnfig {
#Bean
#Qualifier("entryPoint")
AuthenticationEntryPoint loginUrlAuthenticationEntryPoint() {
return new LoginUrlAuthenticationEntryPoint("/login");
}
}
I autowire the field this way
#Autowired
#Qualifier("entryPoint")
private AuthenticationEntryPoint loginUrlAuthenticationEntryPoint;
Stacktrace of the error :
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.env.Environment' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1716) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1272) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1226) ~[spring-beans-5.2.6.RELEASE.jar:5.2.6.RELEASE]
EDIT
I Have another implementation of AuthenticationEntryPoint interface :
#Component
public class CustomAuthenticationEntryPoint extends BasicAuthenticationEntryPoint
But in my opinion it doesn't explain the error (as long as i specify the qualifiers)
You're mixing bean name and Qualifier
#Bean(name="someFancyBean")
public ClassXyx fooBar(){
return new ClassXyz()
}
In this example, method fooBar creates a bean of type ClassXyx and it's named someFancyBean. If you want to auto-wire this bean then you have to use
#Service
class SomeFancyService{
#Autowired #Qualifier("someFancyBean") ClassXyx xyz;
}
A configuration class can create multiple beans of the same type but their names are derived from function name. There's no point in using Bean annotation with name="XYZ" unless you want to rename that bean.
The Qualifier annotation is used for referring one of the beans of the same type.
Now coming back to your code
#Configuration
#EnableWebSecurity
public class CustomSecurityCOnfig {
#Bean
public AuthenticationEntryPoint entryPoint() {
return new LoginUrlAuthenticationEntryPoint("/login");
}
}
In your service you have to Autowired as.
#Autowired
#Qualifier("entryPoint")
private AuthenticationEntryPoint loginUrlAuthenticationEntryPoint;
Also, I would like to point one more thing bean accessibility across package/class.
Generally, all beans created by Spring IOC are public, but it has the same access modifier like Java classes. If you're creating a bean with package scope then you can't auto-wire in another package. Similarly, if a bean is created using private then that bean can be only auto-wired in that class.
I am making a very silly mistake but not able to figure out how to fix.
I have a simple SpringBoot app using profiles, which connect to MongoDb.
My pom.xml dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
My StudentController.java
#RestController
#RequestMapping("/students")
public class StudentController {
#Autowired
private StudentService studentService;
#RequestMapping(method = RequestMethod.GET)
public Collection<Student> getAllStudents(){
return studentService.getAllStudents();
}
}
My StudentService.java
#Service
public class StudentService {
#Autowired
private StudentDao studentDao;
public Collection<Student> getAllStudents(){
return this.studentDao.getAllStudents();
}
}
My StudentDao.java interface:
public interface StudentDao {
Collection<Student> getAllStudents();
}
My MongoStudentDaoImpl.java:
#Repository
#Profile("test")
public class MongoStudentDaoImpl implements StudentDao {
#Autowired
private MongoStudentRepo repo;
#Override
public Collection<Student> getAllStudents() {
return repo.findAll();
}
}
My MongoStudentRepo.java:
#Profile("test")
public interface MongoStudentRepo extends MongoRepository<Student, String> {
}
When I am trying to start the application using the "test" profile, here is the error I am seeing:
Exception encountered during context initialization - cancelling
refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'studentController': Unsatisfied
dependency expressed through field 'studentService'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'studentService': Unsatisfied dependency
expressed through field 'studentDao'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'mongoStudentDaoImpl': Unsatisfied
dependency expressed through field 'repo'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'MongoStudentRepo' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
What am I missing in here? Do I need to add an annotation to MongoStudentRepo.java?
Thanks in advance.
The stacktrace shows that spring is not able to autowire one of the beans MongoStudentRepo in your MongoStudentDaoImpl.java class.From the stacktrace :
Unsatisfied dependency expressed through field 'repo'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'MongoStudentRepo' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:
Spring throwing this exception means that the bean of MongoStudentRepo.class is not getting created properly.
Possible solution :
The issue might be because spring is not creating a bean for your interface using the default implementation in spring.This might be because you are not using the annotation #EnableJpaRepositories to enable scanning and creation of default repository bean.For more information read here
.
But if you are using xml based configuration,
For xml based configuration use :
<repositories base-package="com.acme.repository" />
<repositories base-package="com.acme.repository" repository-impl-postfix="MyPostfix" />
Or using the #Configuration annotation :
#Configuration
#EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {
#Bean
EntityManagerFactory entityManagerFactory() {
// …
}
}
You can load this configuration only for your 'test' profile when you are using the spring default implementation.
Best read : https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.custom-implementations
Your interface class does not need to be annotated, as Spring Data repository interfaces are handled specially by Spring Data.
The most likely case is that your repository class isn't getting identified by Spring Data (you didn't specify a Spring Boot version or package names), in which case you may need #EnableMongoRepositories on an #Configuration class (your Spring Boot launcher class is also one of these).
My apologies, I had missed out on exclude criteria I had added to the Main.java class to make another profile working.
#Chrylis, thanks for your pointer.
Problematic Main.java file
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class})
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Fixed Main.java file
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class})
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
I think for Spring Data MongoDB, adding the #EnableMongoRepositories annotation to a #Configuration class is all you need. Just make sure it's under the same package as your main application, or configure component scan to pick it up.
I'd like to autowire a CrudRespository<Type,Key> in an abstract parent class, then use it with the child classes. Error tells me:
java.lang.IllegalStateException: Failed to load ApplicationContext
[...]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'accountExtractor': Unsatisfied dependency expressed through field 'repository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.repository.CrudRepository<com.finnwa.adwords.adconnect.Account, java.lang.Long>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Abstract parent defining the dependency.
#Component
public abstract class Extractor<T,KEY> {
#Autowired
protected CrudRepository<T,KEY> repository;
// some business logic
}
Child class providing the parameters.
#Component
class AccountExtractor extends Extractor<Account, Long>{
// some config
}
Other classes that might be relevant:
public interface AccountRepository extends CrudRepository<Account, Long>{}
#SpringBootApplication
#EnableJpaRepositories(basePackages = "package.my")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
I learned from other questions that the dependency in the parent class may not be private. So I made it protected. Anything I'm missing?
EDIT: So Paul Janssens and M. Deinum have posted some nice workarounds. But why doesn't this work? What is going wrong here?
For starters I suggest not to use field injection, rather use constructor injection. I would also suggest to use the specific type, as with generics the change is that the type information is removed.
I would probably do something like
public abstract class Extractor<T,KEY> {
private final CrudRepository<T,KEY> repository;
protected Extractor(CrudRepository<T, KEY> repository) {
this.repository=repository;
}
}
Then in your specific class use the AccountRepository and pass it to the super class.
#Component
class AccountExtractor extends Extractor<Account, Long>{
AccountExtractor(AccountRepository repository) {
super(repository);
}
}
This way in your super class and methods you still can use the base type CrudRepository. The added advantage is also that you can now quite easily write a unit test for the AcountExtractor and simply mock the AccountRepository without you having to bootstrap a Spring Boot application. (I know you could use #DataJpaTest but none the less a simple mock is faster).
just use an abstract method and perform the wiring in the subclass
public abstract CrudRepository<T,KEY> getRepository();
...
FooRepository implements CrudRepository<Foo,Integer>
...
#Autowired
protected FooRepository repository;
#Override
public CrudRepository<Foo,Integer> getRepository() {
return repository;
}
I would say that AccountRepository lacks the "magic annotation":
#Repository // This tells Spring Data to actually create a "standard" repository instance for us
public interface AccountRepository extends CrudRepository<Account, Long>{}
For several days I'm trying to create Spring CRUD application. I'm confused.
I can't solve this errors.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'clientController': Unsatisfied dependency expressed through method 'setClientService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'clientService': Unsatisfied dependency expressed through field 'clientRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kopylov.repository.ClientRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
and this
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'clientService': Unsatisfied dependency expressed through field 'clientRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kopylov.repository.ClientRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
ClientController
#Controller
public class ClientController {
private ClientService clientService;
#Autowired
#Qualifier("clientService")
public void setClientService(ClientService clientService){
this.clientService=clientService;
}
#RequestMapping(value = "registration/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute Client client){
this.clientService.addClient(client);
return "home";
}
}
ClientServiceImpl
#Service("clientService")
public class ClientServiceImpl implements ClientService{
private ClientRepository clientRepository;
#Autowired
#Qualifier("clientRepository")
public void setClientRepository(ClientRepository clientRepository){
this.clientRepository=clientRepository;
}
#Transactional
public void addClient(Client client){
clientRepository.saveAndFlush(client);
}
}
ClientRepository
public interface ClientRepository extends JpaRepository<Client, Integer> {
}
I looked through a lot of similar questions, but no one answer to them can't help me.
The ClientRepository should be annotated with #Repository tag.
With your current configuration Spring will not scan the class and have knowledge about it. At the moment of booting and wiring will not find the ClientRepository class.
EDIT
If adding the #Repository tag doesn't help, then I think that the problem might be now with the ClientService and ClientServiceImpl.
Try to annotate the ClientService (interface) with #Service. As you should only have a single implementation for your service, you don't need to specify a name with the optional parameter #Service("clientService"). Spring will autogenerate it based on the interface' name.
Also, as Bruno mentioned, the #Qualifier is not needed in the ClientController as you only have a single implementation for the service.
ClientService.java
#Service
public interface ClientService {
void addClient(Client client);
}
ClientServiceImpl.java (option 1)
#Service
public class ClientServiceImpl implements ClientService{
private ClientRepository clientRepository;
#Autowired
public void setClientRepository(ClientRepository clientRepository){
this.clientRepository=clientRepository;
}
#Transactional
public void addClient(Client client){
clientRepository.saveAndFlush(client);
}
}
ClientServiceImpl.java (option 2/preferred)
#Service
public class ClientServiceImpl implements ClientService{
#Autowired
private ClientRepository clientRepository;
#Transactional
public void addClient(Client client){
clientRepository.saveAndFlush(client);
}
}
ClientController.java
#Controller
public class ClientController {
private ClientService clientService;
#Autowired
//#Qualifier("clientService")
public void setClientService(ClientService clientService){
this.clientService=clientService;
}
#RequestMapping(value = "registration", method = RequestMethod.GET)
public String reg(Model model){
model.addAttribute("client", new Client());
return "registration";
}
#RequestMapping(value = "registration/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute Client client){
this.clientService.addClient(client);
return "home";
}
}
I know it seems too late, but it may help others in future.
I face the same error and the problem was that spring boot did not read my services package so add:
#ComponentScan(basePackages = {"com.example.demo.Services"}) (you have to specify your own path to the services package) and in the class demoApplication (class that have main function) and for service interface must be annotated #Service and the class that implement the service interface must be annotated with #Component, then autowired the service interface.
Try adding #EntityScan(basePackages = "insert package name here") on top of your main class.
If you are using Spring Boot, your main app should be like this (just to make and understand things in simple way) -
package aaa.bbb.ccc;
#SpringBootApplication
#ComponentScan({ "aaa.bbb.ccc.*" })
public class Application {
.....
Make sure you have #Repository and #Service appropriately annotated.
Make sure all your packages fall under - aaa.bbb.ccc.*
In most cases this setup resolves these kind of trivial issues. Here is a full blown example. Hope it helps.
That might happen because the pojos you are using lack of the precise constructor the service needs. That is, try to generate all the constructors for the pojo or objects (model object) that your serviceClient uses, so that the client can be instanced correctly. In your case,regenerate the constructors (with arguments)for your client object (taht is your model object).
I just added the #Repository annotation to Repository interface and #EnableJpaRepositories ("domain.repositroy-package") to the main class. It worked just fine.
The application needs to be placed in the same directory as the scanned package:
I was facing the same issue, and it was, as i missed marking my DAO class with Entity annotations. I tried below and error got resolved.
/**
*`enter code here`
*/
#Entity <-- was missing earlier
public class Topic {
#Id
String id;
String name;
String desc;
.
.
.
}
Add #Repository annotation to the Spring Data JPA repo
According to documentation you should set XML configuration:
<jpa:repositories base-package="com.kopylov.repository" />
Considering that your package scanning is correctly set either through XML configuration or annotation based configuration.
You will need a #Repository on your ClientRepository implementation as well to allow Spring to use it in an #Autowired. Since it's not here we can only suppose that's what's missing.
As a side note, it would be cleaner to put your #Autowired/#Qualifier directly on your member if the setter method is only used for the #Autowired.
#Autowired
#Qualifier("clientRepository")
private ClientRepository clientRepository;
Lastly, you don't need the #Qualifier is there is only one class implementing the bean definition so unless you have several implementation of ClientService and ClientRepository you can remove the #Qualifier
I had the exactly same issue, with a very very long stack trace.
At the end of the trace I saw this:
InvalidQueryException: Keyspace 'mykeyspace' does not exist
I created the keyspace in cassandra, and solved the problem.
CREATE KEYSPACE mykeyspace
WITH REPLICATION = {
'class' : 'SimpleStrategy',
'replication_factor' : 1
};
Check out the table structure of Client table, if there is a mismatch between table structure in db and the entity, you would get this error..
I had this error which was coming due to datatype mismatch of primary key between db table and the entity ...
If you describe a field as criteria in method definition ("findBy"), You must pass that parameter to the method, otherwise you will get "Unsatisfied dependency expressed through method parameter" exception.
public interface ClientRepository extends JpaRepository<Client, Integer> {
Client findByClientId(); ////WRONG !!!!
Client findByClientId(int clientId); /// CORRECT
}
*I assume that your Client entity has clientId attribute.
That was the version incompatibility where their was the inclusion of lettuce. When i excluded , it worked for me.
<!--Spring-Boot 2.0.0 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
There is another instance still same error will shown after you doing everything above mentioned. When you change your codes accordingly mentioned solutions make sure to keep originals. So you can easily go back. So go and again check dispatcher-servelet configuration file's base package location. Is it scanning all relevant packages when you running application.
<context:component-scan base-package="your.pakage.path.here"/>
Add #Component annotation just above the component definition
This error can occur if there are syntax errors with Derived Query Methods. For example, if there are some mismatches with entity class fields and the Derived methods' names.
See if your <context:component-scan base-package="your package "/> is missing in either config or context xml file
I was facing this issue because of duplicate column name staffId and staff_id in same entity class.
private Integer staffId;
#ManyToOne(cascade = CascadeType.ALL, optional = false)
#JoinColumn(name = "staff_id")
private User user;
My issue got resolved by adding "value" & "nativeQuery" tags in #Query annotation like this:
#Query(value = "select * from employee e where e.email_address = ?1", nativeQuery = true)
In my case, I was using dependency of spring boot 3 in spring boot 4.
make sure you use latest dependency version.
you can find that here https://mvnrepository.com/
I was facing the same issue. In my Product Entity Class I had imported #Id from org.springframework.data.annotation.Id and this was causing the error.
It was fixed after I change it to import jakarta.persistence.Id;
Just add #Service annotation to top of the service class