I am attempting to create a Spring Boot test class which should create the Spring context and autowire the service class for me to test.
This is the error I am getting:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.gobsmack.gobs.base.service.FileImportService' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
The file structue:
The Test class:
package com.example.gobs.base.service;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import lombok.val;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
#DataJpaTest
#RunWith(SpringRunner.class)
public class FileImportServiceTest {
#Autowired
private FileImportService fileImportService;
private FileImportEntity entity;
The Main application class:
package com.example.gobs.base;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Used only for testing.
*/
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
FileImportService interface:
package com.example.gobs.base.service;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import java.util.List;
public interface FileImportService {
/**
* List all {#link FileImportEntity}s.
Which is implemented by:
package com.example.gobs.base.service.impl;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import com.example.gobs.base.repository.FileImportRepository;
import com.example.gobs.base.service.FileImportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
#Service
#Transactional
public class FileImportServiceImpl implements FileImportService {
#Autowired
private FileImportRepository repository;
#Override
public List<FileImportEntity> listAllFileImportsByType(FileImportType type) {
return repository.findAllByType(type.name());
}
Why can it not find the implementation?
#DataJpaTest annotation doesn't make services loaded to the application context. From Spring documentation: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test
You can use the #DataJpaTest annotation to test JPA applications. By default, it scans for #Entity classes and configures Spring Data JPA repositories. If an embedded database is available on the classpath, it configures one as well. Regular #Component beans are not loaded into the ApplicationContext.
You could use #SpringBootTest annotation instead of DataJpaTest. Hope that helps!
Related
I am trying to connect spring boot application with MySQL for that I have created a interface with name FilterDao which extend JpaRepository class. but whenever I try to make object of implemented class in Service I got this error "Consider defining a bean of type 'com.example.filter.FilterDao' in your configuration" as I am new to spring boot I don't understand this error.
FilterApplication.java
package com.example.filter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class FilterApplication {
public static void main(String[] args) {
SpringApplication.run(FilterApplication.class, args);
}
}
FilterDao.java
package com.example.filter;
import com.example.filter.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.FluentQuery;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
//#Configuration
public interface FilterDao extends JpaRepository<Filter, Integer> {
}
FilterService.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class FilterService {
#Autowired
private FilterDao filterDao;
public List<Filter> getData() {
System.out.println("----------------------HERE-------------");
return filterDao.findAll();
}
}
FilterConnector.java
package com.example.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class FilterConnector {
#Autowired
private FilterService filterService;
#GetMapping("/home")
public List<Filter> home()
{
return this.filterService.getData();
}
}
Project Structure
Annotate FilterDao with #Repository
Seems spring has not created bean for FilterDao repository and you are trying to use that`
#Autowired
private FilterDao filterDao;`
There might different reasons for this exception. Please try the below solution.
Use #EnableJpaRepositories(basePackages = "com.example.filter") with your FilterApplication class.
Use #ComponentScan(basePackages = "com.example.*") with FilterApplication class
Use #Repoitory annotation with FilterDao interface.
Hope this helps. For more details check the below tutorial.
https://javatute.com/jpa/consider-defining-a-bean-of-type-in-your-configuration/
I have a Data Loader Class which is suppose to load data once the app starts.
My Error -
Could not autowire. No beans of 'OwnerService' Found.
However, my ownerService class is annotated as I have shown below -
This is the class whose supposed to do that -
DataLoader
import model.Owner;
import model.Vet;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import services.OwnerService;
import services.VetService;
import services.map.OwnerServiceMap;
import services.map.VetServiceMap;
#Component
public class DataLoader implements CommandLineRunner {
private final OwnerService ownerService;
private final VetService vetService;
public DataLoader(OwnerService ownerService, VetService vetService) {
this.ownerService = ownerService;
this.vetService = vetService;
}
OwnerServiceMap
package services.map;
import model.Owner;
import org.springframework.stereotype.Service;
import services.OwnerService;
import java.util.Set;
#Service
public class OwnerServiceMap extends AbstractMapService<Owner,Long> implements OwnerService
{//some code here}
The vetService is the same as ownerService.
My applcation class -
package petclinic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class PetclinicApplication {
public static void main(String[] args) {
SpringApplication.run(PetclinicApplication.class, args);
}
}
Maybe I have hierarchy problems, as the application class doesn't search for beans in enough places in the project?
Thank you!
I read a lot about this kind of problem here, but it seems my code is good but the autowire is not working :
Error creating bean with name 'optionController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private service.InteractionBanque controllers.OptionController.interactionBanque; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [service.InteractionBanque] 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)}
Here is the code of my Controller :
package controllers;
package controllers;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import model.Banque;
import model.Client;
import service.InteractionBanque;
import serviceimpl.InteractionBanqueImpl;
#Controller
public class OptionController {
#Autowired
private InteractionBanque interactionBanque;
#RequestMapping(value="/virement",method=RequestMethod.GET)
public String index(Model model, #ModelAttribute Client client) {
model.addAttribute("virement", new Virement());
return "virement";
}
#RequestMapping(value="/virement",method=RequestMethod.POST)
public String index(#ModelAttribute Virement virement, Model model) {
return "options";
}
}
And the Code of my Service :
package serviceimpl;
import java.util.HashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import dao.BanqueDAO;
import daoimpl.BanqueDaoImpl;
import model.Banque;
import model.Client;
import service.InteractionBanque;
import utils.SendRequest;
#Service
public class InteractionBanqueImpl implements InteractionBanque {
public static final int END_ID_BANQUE = 5;
public static final String LOGIN_URL = "/account";
public boolean connecter(Client client) {
some code
}
}
And The code of the interface :
package service;
public interface InteractionBanque {
boolean connecter(Client client);
}
And my Application class define the #SpringBootApplication which should be use to wire everything :
package controllers;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
SO I don't get it, for me this should do the work but the autowired is not working.
Help would be appreciated :)
#SpringBootApplication scans only package (recursively) within a class that uses it. InteractionBanqueImpl is in another package.
Create a package 'app' with Application class, and then move to it controllers and and other packages. Should be fine.
As #Mati said, you have a problem with packages.
Create a root package for your application and move everything under it, so you have it something like this:
+ myapp
Application.java
+ controller
+ service
+ serviceimpl
The answers you have about putting your Application class in a parent package of the rest of your code will work, but an alternative, if you don't want to change your package structure, would be to use the #ComponentScan annotation, specifying the packages that contain components you want to autowire, for example:
#ComponentScan(basePackages = {"serviceimpl", ...}
I try to use Springs own Dependency Injection in a Junit test case:
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.binarisinformatik.api.AppConfig;
import org.binarisinformatik.satzrechner.SatzRechner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=AppConfig.class)
//#SpringApplicationConfiguration(classes = {AppConfig.class})
public class SatzRechnerTest {
#Autowired
private SatzRechner satzRechner; //SUT
#Before
public void setUp() {
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SatzRechnerTest.class);
//satzRechner=context.getBean(SatzRechner.class);
}
#Test
public void addiere_satz_4komma6_zu_zahlwert_10() {
assertThat("Addition von \"4,6\" ergibt nicht 10!",
satzRechner.summe("4,6"), is(equalTo(10)));
}
Im testing a class names SatzRechner in which Spring should also autowire some variables. Here is my Class under test:
#Component
public class SatzRechner {
#Autowired //#Inject
private Rechner taschenRechner;
#Autowired
private Zahlenfabrik zahlenfabrik;
public Integer summe(String zeichenSatz) {
return taschenRechner.summe(zahlenfabrik.erzeugeZahlen(zeichenSatz));
}
}
And AppConfig.class which is using as Configurationfile looks like that:
#Configuration
#ComponentScan(value={"org.binarisinformatik"})
public class AppConfig {
}
What is here the problem?
If you want to use a Spring configuration class, this one must have beans definitions. Please find an example below :
Test class:
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.binarisinformatik.api.AppConfig;
import org.binarisinformatik.satzrechner.SatzRechner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=AppConfig.class)
public class SatzRechnerTest {
#Autowired
private SatzRechner satzRechner;
#Test
public void addiere_satz_4komma6_zu_zahlwert_10() {
assertThat("Addition von \"4,6\" ergibt nicht 10!",
satzRechner.summe("4,6"), is(equalTo(10)));
}
}
Configuration class :
You have to declare #Bean annotated methods. These beans are managed by Spring container.
#Configuration
public class AppConfig {
// Beans present here will be injected into the SatzRechnerTest class.
#Bean
public SatzRechner satzRechner() {
return new SatzRechner();
}
#Bean
public Rechner taschenRechner() {
return new TaschenRechner();
}
#Bean
public Zahlenfabrik zahlenfabrik() {
return new Zahlenfabrik();
}
}
Note : I let you properly handle returned types here and beans parameters (if present in your context).
There are two things you have to ensure before you run the test case successfully:
1) Classes SatzRechner, Rechner & Zahlenfabrik should be under "org.binarisinformatik" package
2) Classes Rechner & Zahlenfabrik should also be annotated with #Component as SatzRechner.
How to autowire Service in test class by only using spring-annotations
when I try I got this error below , whereas #Service annotation used in UserServiceImp class
2014-12-20 15:35:52 ERROR TestContextManager:334 - Caught exception
while allowing TestExecutionListener
[org.springframework.test.context.support.DependencyInjectionTestExecutionListener#5af97850]
to prepare test instance [com.amsb.bariz.base.test.UserTest#4520ebad]
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'com.amsb.bariz.base.test.UserTest': Injection
of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: public com.amsb.bariz.base.service.UserService
com.amsb.bariz.base.test.UserTest.userService; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.amsb.bariz.base.service.UserService]
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)}
my Service Class is
package com.amsb.bariz.base.service.imp;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.amsb.bariz.base.dao.UserDao;
import com.amsb.bariz.base.dao.UserRoleDao;
import com.amsb.bariz.base.entity.User;
import com.amsb.bariz.base.entity.UserRole;
import com.amsb.bariz.base.service.UserService;
#Service("userService")
public class UserServiceImp implements UserService {
#Autowired
private UserDao userDao;
#Autowired
private UserRoleDao userRoleDao;
public void register(User user) {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
user.setPassword(passwordEncoder.encode(user.getPassword()));
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Date dateNow = new Date(20070266);
Timestamp dn = new Timestamp(now.getTime());
user.setStatus("P");
user.setCreated_on(dn);
user.setEnabled(false);
UserRole ur = new UserRole(user,"USER_ROLE");
System.out.println("XDXDX ::" + user.toString());
userDao.create(user);
userRoleDao.create(ur);
}
}
my Test Class is :
package com.amsb.bariz.base.test;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import com.amsb.bariz.base.dao.UserDao;
import com.amsb.bariz.base.entity.User;
import com.amsb.bariz.base.entity.UserRole;
import com.amsb.bariz.base.service.UserService;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import junit.framework.TestCase;
import junit.framework.TestSuite;
#Configuration
#ComponentScan(basePackages={"com.amsb.bariz.base.service"})
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:spring/spring-main.xml"})
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
public class UserTest {
#Autowired
public UserService userService;
#Test
public void userAdd() {
User user = new User();
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Timestamp doo = new Timestamp(now.getTime());
Date a = new Date(0);
user.setPassword("oman");
user.setName("oman new ");
user.setStatus("N");
user.setCreated_on(doo);
user.setUpdated_on(doo);
user.setDob(new Date(20140522));
user.setUsername("AHMED#A.com");
userService.register(user);
}
}
Are you trying to use the test itself as a part of the Spring configuration? That's not going to work. What you need to do is:
- remove the #Configuration and #ComponentScan annotations from the test itself
- create a simple TestConfiguration class:
#Configuration
#ComponentScan(basePackages={"com.amsb.bariz.base.service"})
#ImportResource("classpath:spring/spring-main.xml")
public class TestConfiguration{ }
And just reference that in your test:
#ContextConfiguration(classes = { TestConfiguration.class }, loader = AnnotationConfigContextLoader.class)
public class UserTest {
And you should be able to inject your service just fine.
Hope it helps.