NoSuchBeanDefinitionException : no qualifying bean of type - spring

I get this error when call my GET request (modes-calcul) and I don't understand why... My dependency injection is correct?
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.margaux.margaux.repository.ModeCalculDAO' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
ModeCalculController :
#Slf4j
#Transactional
#RestController
#RequestMapping("modes-calcul")
public class ModeCalculController {
private ModeCalculService modeCalculService;
#Autowired
public ModeCalculController(ModeCalculService modeCalculService) {
this.modeCalculService = modeCalculService;
}
#GetMapping()
public ResponseEntity<List<ModeCalculDTO>> getModesCalcul() {
return new ResponseEntity<List<ModeCalculDTO>>(modeCalculService.getModesCalcul(), HttpStatus.OK);
}
}
ModeCalculServiceImpl :
#Slf4j
#Service
#Transactional
public class ModeCalculServiceImpl implements ModeCalculService {
private ModeCalculDAO modeCalculDAO;
#Autowired
#Lazy
public ModeCalculImpl(ModeCalculDAO modeCalculDAO){
this.modeCalculDAO = modeCalculDAO;
}
#Override
public List<ModeCalculDTO> getModesCalcul() {
ModelMapper mapper = new ModelMapper();
List<ModeCalcul> modesCalcul = modeCalculDAO.findAll();
return modesCalcul
.stream()
.map(modeCalcul -> mapper.map(modeCalcul, ModeCalculDTO.class))
.collect(Collectors.toList());
}
}
ModeCalculDAO :
#Repository
public interface ModeCalculDAO extends JpaRepository<ModeCalcul, Long> {
}
Thanks for your help..

check whether the ModeCalculDAO is in sub package of main program
or if it is not a sub package try to add #ComponentScan(package name) in main program

When you run your application it scans all the files which are inside the sub package of the project main package in which your main class has defined using #SpringBootApplication. So put all the files inside the sub package of your main class that you want to scan or if your package is not a subpackage of your main package use #ComponentScan(your_package name) at your main class.

Make sure your MargauxApplication class to be inside com.margaux.margaux package.
Can you please share MargauxApplication class to check its import packages.

Here is the MargauxApplication class :
package com.margaux.margaux;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class MargauxApplication {
public static void main(String[] args) {
SpringApplication.run(MargauxApplication.class, args);
}
}
I tried to put #ComponentScan("com.margaux.margaux") or #ComponentScan(basePackages = "com.margaux.margaux")
in this class but it doesn't work.
My other classes have this :
package com.margaux.margaux.repository;
package com.margaux.margaux.service;
etc ...
in my pom I have this:
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.3.6.RELEASE</version>
</dependency>
if I put this, it works :
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Why ?

Related

No qualifying bean of type available: expected at least 1 bean which qualifies as autowire candidate

I am learning Spring Dependency Injections and to do so I wrote small simple code, but I constanstly get this error:
No qualifying bean of type available available: expected at least 1 bean which qualifies as autowire candidate.
Can anyone point me in the right direction? Thanks!
Service.java
package net.ddns.encante.test2.Spring.SpringTest2;
import org.springframework.stereotype.Component;
#Component
public class Service {
void doService (){
System.out.println("Service is running");
}
}
Controller.java
package net.ddns.encante.test2.Spring.SpringTest2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Controller {
#Autowired
Service service;
void doControl(){
System.out.println("Controlling, move along");
}
void doServiceByController(){
service.doService();
}
}
SpringTest2Application.java
package net.ddns.encante.test2.Spring.SpringTest2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
#SpringBootApplication
public class SpringTest2Application {
public static void main(String[] args) {
SpringApplication.run(SpringTest2Application.class, args);
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Controller.class);
ctx.refresh();
Controller ctrl = ctx.getBean(Controller.class);
ctrl.doServiceByController();
}
}
I tried different combinations of #Component and #Autowired annotations but it doesn't help.
The problem is your code.
SpringApplication.run(SpringTest2Application.class, args);
This already creates everything you need. However you discard it and try to shoehorn something in there.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Controller.class);
ctx.refresh();
Controller ctrl = ctx.getBean(Controller.class);
ctrl.doServiceByController();
This will create another application context, and only for the Controller nothing else.
Instead, if you read the javadoc of the run method you can see that that already returns an ApplicationContext. Which is the one you should be using in the first place.
ApplicationContext ctx = SpringApplication.run(SpringTest2Application.class, args);
Controller ctrl = ctx.getBean(Controller.class);
ctrl.doServiceByController();
Is all you need.

Spring Boot AOP in multi module project does not execute Before Advice

I'm doing my fist steps with Springs AOP and wanted to start with a simple logging advice. My project is a multi module maven project with the following structure:
parentProject
|__aop
|__data
|__web
The web module has a user service class in the package de.my.awsome.project.web.service with a saveNewUser Method:
#Service
public class UserService {
...
public MdUser saveNewUser(UserModel user) {
MdUser newUser = this.save(user);
createGroupMembership(user, newUser);
return newUser;
}
}
The method works as expected so don't bother with details about that.
What I've done now is to create the following class in the aop module:
#Component
#Aspect
public class LoggingAspect {
Logger logger = Logger.getLogger(getClass());
#Before("execution(public * de.my.awsome.project.web.service.UserService.saveNewUser(..))")
public void newUserLog(JoinPoint joinpoint) {
logger.info(joinpoint.getSignature() + " with user " + joinpoint.getArgs()[0]);
}
}
I added a dependency for the web module in the pom of the aop module:
<dependency>
<groupId>de.my.awsome.project</groupId>
<artifactId>web</artifactId>
<version>${project.version}</version>
</dependency>
I even wrote a ConfigurationClasse even though I thought this would not be necessary with SpringBoot:
#Configuration
#ComponentScan(basePackages="de.fraport.bvd.mobisl.aop")
public class AspectsConfig {
}
The expected result is a log-message like "saveNewUser with user xyz". But the logging method is never called. What have I missed to do?
#Configuration - Indicates that this file contains Spring Bean Configuration for an Aspect.
Replace #Component with #Configuration for LoggingAspect.
Well, the answer that #sankar posted didn't work either but I found the solution by myself.
I had to add a dependency to my aop module in the web modules pom, not vice versa. Then I added an Import of my AspectsConfig to the web modules SpringBootApplication class and it worked.
#SpringBootApplication
#Import(value= {JPAConfig.class, AspectsConfig.class})
#EnableAspectJAutoProxy
public class WebApplication {
#Autowired
private JPAConfig config;
#Autowired
private AspectsConfig aspectConfig;
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
The following steps work for me - see below if anyone is looking for a solution
add the aop dependency in to the main parent pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
add your Aspect implementation in he aop-sub-module
#Aspect
#Component
public class SampleAspect {
#After("execution(* de.my.awsome.project.testMethod())")
public void logAuditActivity(JoinPoint jp) {
System.out.println("TESTING ****************");
System.out.println("The method is called");
}
In your other submodule (web-submodule) add the dependancy of the aspect-submodule
<dependency>
<groupId>de.my.awsome.project</groupId>
<artifactId>aop</artifactId>
</dependency>
In your web Project include the aop package for component scan
eg. if SampleAspect is under a package de.my.awsome.project you will need to add in as follow
#ComponentScan(basePackages = {"de.my.awsome.project", "de.my.awsome.aop" }
clean build and run the app

No qualifying bean of type repository when running test but not main application

I'm developing a Spring Boot application following TDD methodology. I've created the main classes (controller, service and repository) this way:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class CrimeServiceImpl implements CrimeService{
#Autowired
private CrimeRepository repository;
...
Controller:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class CrimeController {
#Autowired
private CrimeServiceImpl service = new CrimeServiceImpl();
Repository:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CrimeRepository extends JpaRepository<Crime, Long>{
}
This is the project structure:
If I run the application normally, no error. The classes' methods are empty. Then I've created a test class like this:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = CrimeServiceImpl.class)
#ComponentScan("com.springmiddleware")
#AutoConfigureMockMvc
#SpringBootTest
public class TestCrimeService {
//Calling method getAllCrimes works
#Test
public void returnAllCrimesExists() throws NoSuchMethodException, SecurityException {
List<Crime> list = new ArrayList<>();
assertTrue(this.service.getAllCrimes() == list);
}
And if I run this, the following error is shown and the test fails:
NoSuchBeanDefinitionException: No qualifying bean of type 'com.springmiddleware.repository.CrimeRepository' available: expected at least 1 bean which qualifies as autowire candidate.
I've checked all annotations and it seems to me that all is ok, and I thought if I missed something, even in the normal run the application would fail. What did I got wrong?
I wanted also to make a test class for a JPARepository, and I also encountered the same error message:
NoSuchBeanDefinitionException: No qualifying bean of type
'SomethingRepository' available:
expected at least 1 bean which qualifies as autowire candidate.
I could make it work by adding the 2 following annotations on top of the test class:
#EnableJpaRepositories(basePackageClasses = SomethingRepository.class) // repository
#EntityScan(basePackageClasses = Something.class) // entity of the repository
Now it looks like:
#RunWith(SpringRunner.class)
#EnableJpaRepositories(basePackageClasses = SomethingRepository.class) // repository
#EntityScan(basePackageClasses = Something.class) // entity of the repository
#SpringBootTest(classes = MyDbUnitTestApp.class) // does some #ComponentScan and #EntityScan on the repositories/entities package, and #EnableAutoConfiguration
#ActiveProfiles(Profiles.myTestProfile)
#DatabaseSetup(value = {
"/datasets/dataset1.xml" }, type = DatabaseOperation.CLEAN_INSERT)
public class SomethingRepositoryTest {
#Autowired
private SomethingRepository sut;
#Test
public void findById() {
Something something= sut.findById(1L);
Assert.assertEquals("foobar", something.getName());
}
}

How to autowire #ConfigurationProperties into #Configuration?

I have a properties class defined like this:
#Validated
#ConfigurationProperties(prefix = "plugin.httpclient")
public class HttpClientProperties {
...
}
And a configuration class like this:
#Configuration
#EnableScheduling
public class HttpClientConfiguration {
private final HttpClientProperties httpClientProperties;
#Autowired
public HttpClientConfiguration(HttpClientProperties httpClientProperties) {
this.httpClientProperties = httpClientProperties;
}
...
}
When starting my spring boot application, I'm getting
Parameter 0 of constructor in x.y.z.config.HttpClientConfiguration required a bean of type 'x.y.z.config.HttpClientProperties' that could not be found.
Is this not a valid use case, or do I have to declare the dependencies some how?
This is a valid use case, however, your HttpClientProperties are not picked up because they're not scanned by the component scanner. You could annotate your HttpClientProperties with #Component:
#Validated
#Component
#ConfigurationProperties(prefix = "plugin.httpclient")
public class HttpClientProperties {
// ...
}
Another way of doing so (as mentioned by Stephane Nicoll) is by using the #EnableConfigurationProperties() annotation on a Spring configuration class, for example:
#EnableConfigurationProperties(HttpClientProperties.class) // This is the recommended way
#EnableScheduling
public class HttpClientConfiguration {
// ...
}
This is also described in the Spring boot docs.
In Spring Boot 2.2.1+, add the #ConfigurationPropertiesScan annotation to the application. (Note that this was enabled by default in version 2.2.0.) This will allow all classes annotated with #ConfigurationProperties to be picked up without using #EnableConfigurationProperties or #Component.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
#SpringBootApplication
#ConfigurationPropertiesScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Also, to generate metadata for the classes annotated with #ConfigurationProperties, which is used by IDEs to provide autocompletion and documentation in application.properties, remember to add the following dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

Spring Boot #autowired does not work, classes in different package

I have a Spring boot application.
I get the following error
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'birthdayController': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.esri.birthdays.dao.BirthdayRepository
com.esri.birthdays.controller.BirthdayController.repository; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.esri.birthdays.dao.BirthdayRepository]
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)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at or
Following is code of my Repository class
package com.esri.birthdays.dao;
import com.esri.birthdays.model.BirthDay;
public interface BirthdayRepository extends MongoRepository<BirthDay,String> {
public BirthDay findByFirstName(String firstName);
}
Following is controller.
package com.esri.birthdays.controller;
#RestController
public class BirthdayController {
#Autowired
private BirthdayRepository repository;
Works if they are in same package. Not sure why
When you use #SpringBootApplication annotation in for example package
com.company.config
it will automatically make component scan like this:
#ComponentScan("com.company.config")
So it will NOT scan packages like com.company.controller etc.. Thats why you have to declare your #SpringBootApplication in package one level prior to your normal packages like this: com.company OR use scanBasePackages property, like this:
#SpringBootApplication(scanBasePackages = { "com.company" })
OR componentScan:
#SpringBootApplication
#ComponentScan("com.company")
Just put the packages inside the #SpringBootApplication tag.
#SpringBootApplication(scanBasePackages = { "com.pkg1", "com.pkg2", .....})
Let me know.
Try annotating your Configuration Class(es) with the #ComponentScan("com.esri.birthdays") annotation.
Generally spoken: If you have sub-packages in your project, then you have to scan for your relevant classes on project-root. I guess for your case it'll be "com.esri.birthdays".
You won't need the ComponentScan, if you have no sub-packaging in your project.
Try this:
#Repository
#Qualifier("birthdayRepository")
public interface BirthdayRepository extends MongoRepository<BirthDay,String> {
public BirthDay findByFirstName(String firstName);
}
And when injecting the bean:
#Autowired
#Qualifier("birthdayRepository")
private BirthdayRepository repository;
If not, check your CoponentScan in your config.
Spring Boot will handle those repositories automatically as long as they are included in the same package (or a sub-package) of your #SpringBootApplication class. For more control over the registration process, you can use the #EnableMongoRepositories annotation. spring.io guides
#SpringBootApplication
#EnableMongoRepositories(basePackages = {"RepositoryPackage"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
In my case #component was not working because I initialized that class instance by using new <classname>().
If we initialize instance by conventional Java way anywhere in code, then spring won't add that component in IOC container.
For this kind of issue, I ended up in putting #Service annotation on the newly created service class then the autowire was picked up.
So, try to check those classes which are not getting autowired, if they need the corresponding required annotations(like #Controller, #Service, etc.) applied to them and then try to build the project again.
By default, in Spring boot applications, component scan is done inside the package where your main class resides. any bean which is outside the package will not the created and thus gives the above mentioned exception.
Solution: you could either move the beans to the main spring boot class(which is not a good approach) or create a seperate configutation file and import it:
#Import({CustomConfigutation1.class, CustomConfiguration2.class})
#SpringBootpplication
public class BirthdayApplication {
public static void main(String [] args) {
springApplication.run(BirthdayApplication.class, args );
}
}
Add beans to these CustomConfiguration files.
I had the same problem. It worked for me when i removed the private modifier from the Autowired objects.
Another fun way you can screw this up is annotating a setter method's parameter. It appears that for setter methods (unlike constructors), you have to annotate the method as a whole.
This does not work for me:
public void setRepository(#Autowired WidgetRepository repo)
but this does:
#Autowired public void setRepository(WidgetRepository repo)
(Spring Boot 2.3.2)
There will definitely be a bean also containing fields related to Birthday
So use this and your issue will be resolved
#SpringBootApplication
#EntityScan("com.java.model*") // base package where bean is present
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.test.springboot;
#SpringBootApplication
#ComponentScan(basePackages = "com.test.springboot")
public class SpringBoot1Application {
public static void main(String[] args) {
ApplicationContext context= SpringApplication.run(SpringBoot1Application.class, args);
=====================================================================
package com.test.springboot;
#Controller
public class StudentController {
#Autowired
private StudentDao studentDao;
#RequestMapping("/")
public String homePage() {
return "home";
}
When I add #ComponentScan("com.firstday.spring.boot.services") or scanBasePackages{"com.firstday.spring.boot.services"} jsp is not loaded. So when I add the parent package of project in #SpringBootApplication class it's working fine in my case
Code Example:-
package com.firstday.spring.boot.firstday;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.firstday.spring.boot"})
public class FirstDayApplication {
public static void main(String[] args) {
SpringApplication.run(FirstDayApplication.class, args);
}
}

Resources