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
}
Related
I've created this class:
public class ActivitiWorkflowService {
private final TaskService taskService;
..
}
but I have this problem when init the project:
No qualifying bean of
type 'org.activiti.engine.TaskService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
I expect that your class has a constructor such as:
public class ActivitiWorkflowService {
private final TaskService taskService;
public ActivitiWorkflowService(TaskService taskService) {
this.taskService = taskService;
}
}
The error you are getting is because Spring cannot autowire this class to the ActivitiWorkflowService - it probably was not defined in the Spring context.
Depending on the configuration you use you can either:
Define class with #Component or #Service annotation and let #ComponentScan do its work:
#Component //#Service
public TaskService {
...
}
or if you are using #Configuration class define the bean of type TaskService
#Configuration
public class AppConfig {
#Bean
public TaskService taskService() {
return new TaskService();
}
#Bean
public ActivitiWorkflowService activitiWorkflowService(TaskService taskService) {
return new ActivitiWorkflowService(taskService);
}
}
I am writing the integration tests with #WebFluxTest for my #RestController.
Here are my classes:
#RestController
#RequestMapping("/usager")
public class UsagerController {
#Autowired
private UsagerService usagerService;
#GetMapping
public Usager getUsager() {
return usagerService.create();
}
}
#Service
public class UsagerService implements CrudService<Usager, Integer> {
#Autowired
private UsagerRepository usagerRepository;
#Override
public JpaRepository<Usager, Integer> getRepository() {
return usagerRepository;
}
#Override
public Usager create() {
return new Usager();
}
}
#Repository
public interface UsagerRepository extends JpaRepository<Usager, Integer>, JpaSpecificationExecutor<Usager> {
}
#ExtendWith(SpringExtension.class)
#WebFluxTest(UsagerController.class)
#Import({ UsagerService.class, UsagerRepository.class })
#Tag(TestCase.INTEGRATION)
public class UsagerControllerIT {
#Autowired
private WebTestClient wtc;
#Test
public void getUsager_returnUsager() {
ResponseSpec rs = wtc.get().uri("/usager").exchange();
rs.expectStatus().isOk();
rs.expectHeader().contentType(MediaType.APPLICATION_JSON);
rs.expectBody(Usager.class).isEqualTo(new Usager());
}
}
I get the following exception:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.dsi.bibliosys.biblioback.repository.UsagerRepository]: Specified class is an interface
I don't understand why Spring can't inject the repository.
Does somebody have an idea ?
I tried another approach using #SpringBootTest. Here is my new test class :
#ExtendWith(SpringExtension.class)
#SpringBootTest
#Tag(TestCase.INTEGRATION)
public class UsagerController02IT {
#Autowired
private UsagerController usagerController;
#Test
public void getUsager_returnUsager() {
WebTestClient wtc = WebTestClient.bindToController(usagerController).build();
ResponseSpec rs = wtc.get().uri("/usager").exchange();
rs.expectStatus().isOk();
rs.expectHeader().contentType(MediaType.APPLICATION_JSON);
rs.expectBody(Usager.class).isEqualTo(new Usager());
}
}
I get this exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.dsi.bibliosys.biblioback.controller.UsagerController': Unsatisfied dependency expressed through field 'usagerService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.dsi.bibliosys.biblioback.service.entity.UsagerService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I don't understand why UserService is not available in the application context.
Thanks for your help.
This looks very similar to this. I'd suggest investigating your test configuration and adding it if appropriate.
A quote from Spring on #WebFluxTest
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to WebFlux tests (i.e. #Controller, #ControllerAdvice, #JsonComponent, Converter/GenericConverter, and WebFluxConfigurer beans but not #Component, #Service or #Repository beans).
I have the error below when trying to run a springboot application , I am not able to inject the HrEmployeesReportOutput class by using the #Autowired annotation, I tried other ways, but didnt work.
would you please help me with this?
No qualifying bean of type [com.nearshoretechnology.focalpoint.interactors.hremployees.HrEmployeesReportOutput] 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)}
#Controller
#RequestMapping("/management/hr/employees/report")
public class HrManagerEmployeeReportController {
#Autowired
private HrEmployeesReportOutput hrEmployeesReportPresenter;
private HrEmployeesReportInput hrReportEmployees;
#Secured({ HR_ADMIN, BENCH_ADMIN })
#RequestMapping(method = RequestMethod.GET)
public String index(Model model) {
HrEmployeesReportForm form = new HrEmployeesReportForm();
String username = SecurityContextHolder.getContext().getAuthentication().getName();
form.setUsername(username);
this.hrReportEmployees.setReportEmployeesPresenter(hrEmployeesReportPresenter);
model.addAllAttributes(hrReportEmployees.employeeReport(form));
return "management/hr/reports/employees";
}
}
public interface HrEmployeesReportOutput extends InteractorOutput<HrEmployeesReportResult> {
}
public interface InteractorOutput<T> {
Map<String, Object> generateViewModel(T result);
}
public class HrEmployeesReportResult extends BaseResult {}
public class BaseResult {}
public interface HrEmployeesReportInput {
Map<String, Object> employeeReport(HrEmployeesReportForm form);
void setReportEmployeesPresenter(HrEmployeesReportOutput presenter);
}
You should have at least one class which implements your HrEmployeesReportOutput interface
And if you are using #ComponentScan (added automatically if you are using spring-boot) your class must have annotation #Component
For example:
#Component
public class HrEmployeesReportOutputImpl implements HrEmployeesReportOutput{...}
I am using a mock repository for my application.
Here is snippet how service looks:
#Service
public class WeatherStationService {
#Autowired
private WeatherStationRepositoryMock weatherRepository;
Here is repository code:
#Repository
public class WeatherStationRepositoryMock {
#Getter
private List<WeatherStation> stations = new ArrayList<>(
Arrays.asList(
new WeatherStation("huston", "Huston station", RandomGenerator.getRandomGeoInformation()),
new WeatherStation("colorado", "Colorado station", RandomGenerator.getRandomGeoInformation())
)
);
It works fine when I am executing main() with #SpringBootApplication.
However, when I want to run test class:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = MockConfig.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class WeatherStationServiceTest {
#Autowired
#Real
private WeatherStationService weatherService;
It fails with the following stacktrace:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'edu.lelyak.repository.WeatherStationRepositoryMock' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Here is MockConfig content:
#Configuration
public class MockConfig {
//**************************** REAL BEANS ******************************
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
Real is marker annotation for real instances:
#Retention(RUNTIME)
#Qualifier
public #interface Real {
}
I can fix it with next initialization at service:
#Service
public class WeatherStationService {
private WeatherStationRepositoryMock weatherRepository = new WeatherStationRepositoryMock();
It works fine.
Why does this happen?
How to fix autowiring for my custom repository class?
#SpringBootApplication implicitly defines #ComponentScan, which scans all subpackages for beans.
When you run a test using MockConfig's, it doesn't scan for beans.
Solution - use #ComponentScan OR define beans in MockConfig
(1) Using #ComponentScan:
#Configuration
#ComponentScan //Make sure MockConfig is below all beans to discover
public class MockConfig {
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
}
(2) or define required beans:
#Configuration
public class MockConfig {
#Bean
#Real
public WeatherStationService weatherServiceReal() {
return new WeatherStationService();
}
#Bean
public WeatherStationRepositoryMock weatherStationRepository() {
return new WeatherStationRepositoryMock()
}
}
I Create the bean by configuration with out name
#Configuration
#ConfigurationProperties(prefix = "mysql")
public class DbConfiguration extends BaseDbConfiguration {
#Bean//(name = "fix")
#Override
public DbClient createClient() {
return super.createClient();
}
}
usage:
#Autowired
private DbClient dbClient;
when I running application it can't start up
And throw NoSuchBeanDefinitionException:
No qualifying bean of type [DbClient] 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)}
But I fix it by add name, why??
#Bean(name = "fix")
I also add a test such like this:
public class TestCreate {
#NotNull
private int test;
public Test createTest() {
return new Test(this.test);
}
}
it configuration like this:
#Configuration
#ConfigurationProperties(prefix = "test")
public class TestConfiguration extends TestCreate {
#Override
#Bean
public Test createTest() {
return super.createTest();
}
}
And autowired like this:
#Autowired
private Test test;
However, this test may work well
It also create Bean without name and Autowired with out Qualifier
Please Tell me why....thanks
Sorry.
I have found the results:
Overriding bean definition for bean 'createClient': replacing ...
So Spring-Boot will create Bean by FunctionName rather than returning ObjectName.