This super class DAO:
public class CrudDAO{
}
This child class:
#Repository
public class JnsTimeDao extends CrudDAO {
}
#Repository
public class BatchDAO extends CrudDAO {
}
this super service class
#Transactional(readOnly = true)
public abstract class CrudService<D extends CrudDAO> {
#Autowired
protected D dao;
}
startup error:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type [com.gp.dao.CrudDAO] is defined: expected
single matching bean but found 2: batchDAO,jnsTimeDao
There are 2 beans of type CrudDAO. So, Spring won't be able to understand which bean to inject. Can be solved as follows
#Repository("jnsTimeDao")
public class JnsTimeDao extends CrudDAO {
}
#Repository("batchDao")
public class BatchDAO extends CrudDAO {
}
While injecting use #Qualifier
#Transactional(readOnly = true)
public abstract class CrudService<D extends CrudDAO> {
#Autowired
#Qualifier("batchDao")
protected D dao;
}
Related
I'm giving this error:
Parameter 0 of constructor in x.microservice.module.business.application.BusinessCreator required a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=false)
Action:
Consider defining a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' in your configuration.
The controller:
#Slf4j
#RestController
public final class BusinessPostController {
#Autowired
private BusinessCreator creator;
#PostMapping(value = "/business")
public ResponseEntity create(#RequestBody Request request){
BusinessCreatorDto businessCreatorDto = new BusinessCreatorDto(IdentifierEpoch.generate(),request.getName());
return ResponseEntity.ok(
creator.create(businessCreatorDto)
);
}
}
The Application Layer:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}
In the Infrastructure layer
#Repository
public abstract class HibernateJpaRepository implements JpaRepository<Business, Long> {
}
The boot Application:
#EnableJpaRepositories
#SpringBootApplication
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
}
All dependencies are resolved and the others classes I believe that are irrellevant.
Any suggestions? Thank you very much
Probably, the error cause is HibernateJpaRepository - it has to be an interface that extends JpaRepository.
You could write your own Repository in a interface:
#Repository
public interface HibernateJpaRepository extends JpaRepository < Business, Long > {
}
Then your Class:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}
I have the following:
public abstract class ReportGenerationStrategy<T extends ReportParameter> {
public abstract void generate(T reportParameter) throws IOException;
}
The subclasses:
#Component
#AllArgsConstructor
public class DeferredRevenueReportGenerationStrategy extends ReportGenerationStrategy<DeferredRevenueReportParameter> {
}
#Component
#AllArgsConstructor
public class OffBalanceExposureReportGenerationStrategy extends ReportGenerationStrategy<OffBalanceExposureReportParameter> {
}
I am creating a map with the subclasses:
#Bean
public Map<ReportType, ReportGenerationStrategy<? extends ReportParameter>> generationStrategies(
#Qualifier("deferredRevenueReportGenerationStrategy") final ReportGenerationStrategy<? extends ReportParameter> deferredRevenue,
#Qualifier("offBalanceExposureReportGenerationStrategy") final ReportGenerationStrategy<? extends ReportParameter> offBalanceExposure
)
{
return ImmutableMap.of(
ReportType.DEFERRED_REVENUE, deferredRevenue,
ReportType.OFF_BALANCE_EXPOSURE, offBalanceExposure
);
}
And trying to inject the map as following:
#AllArgsConstructor
#Slf4j
public class ReportApplicationServices {
private final Map<ReportType, ReportGenerationStrategy<ReportParameter>> generationStrategies; //Empty map injected
}
But I receive an empty map on the field...
Why is this happening?
I believe you missed to use #Autowire annotation on the private final Map that you have declared.
Hope this helps and solves the issue.
In my Spring Boot 2.0.2 application I am trying to inject a component herited from abstract class which implements an interface and it doesn't work.
Code :
Component Abstract : (Do I need to put #Component ?)
package app.project.service;
#Component
public abstract class AbstractStepService implements IStepService {
protected final void addTask() {
...
}
#Override
public StepDataDto launch() throws StepException {
...
}
}
Interface :
package app.project.service;
public interface IStepService {
StepDataDto launch() throws StepException;
}
package app.project.service;
Component :
#Component
public class CStepServiceImpl extends AbstractStepService implements IStepService {
#PostConstruct
private void defineTasks() {
}
}
package app.project.service;
Junit Test :
#RunWith(SpringRunner.class)
#SpringBootTest
public class CStepServiceTest {
#Autowired
#Qualifier("cStepServiceImpl")
private IStepService service;
}
package app.project;
Application :
#SpringBootApplication
#ComponentScan(basePackages ={"app.project.service"})
public class MyApplication {}
Error message when launching my Junit test :
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'app.project.service.IStepService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=cStepServiceImpl)}
Any idea ?
Thanks
Change your declaration like this
#Autowired
#Qualifier("CStepServiceImpl")
private IStepService service;
or
#Autowired
private IStepService CStepServiceImpl;
That should work. The bean name created automatically by spring has CStepServiceImpl name.
You can also name your bean like this
#Component(value = "myName")
public class CStepServiceImpl extends AbstractStepService implements IStepService {
}
and use myName during Autowiring.
Here is a sample class below
#Service("testService")
public class TestService {
public String something() {
return "abc";
}
}
I want to extend the class and let the container know that it needs to pick up my extended class from now.
#Service("extendedTestService")
public class ExtendedTestServiceMock extends TestService {
#override
public String something() {
return "xyz";
}
}
Test class
public class TestClass extends SpringTest {
#Autowired
#Qualifier("extendedTestService")
private ExtendedTestServiceMock testService;
public void testMethod(){
......
}
}
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [TestService] is defined: expected single matching bean but found 2: ExtendedTestServiceMock,testService
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:865) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.8.RELEASE.jar:3.2.8.RELEASE]
... 91 common frames omitted
How to resolve it?
You haven't defined a bean of type ExtendedTestService.
You have only defined a bean of type ExtendedTestServiceMock.
Try this:
#Autowired
#Qualifier("extendedTestService")
private TestService testService;
The solution is use a #service anotation, you should inject the service like this:
#Autowired
private TestService testService;
And then you can use the methods of TestService
I have the following scenario:
class Super{
private List<String> someStringsThatWillBeDifferentForEveryInstancePerDerivedType;
}
#Component
class Derived1 extends Super{
#Autowired
private String name;
}
#Component
class Derived2 extends Super{
#Autowired
private Long configId;
}
I have a different List defined as Spring bean in xml for each derived class…call them listForDerived1 and listForDerived2. How can I wire these lists into my derived classes? I attempted constructor injection but I can't seem to find any luck injecting both the collection and the other deps.
You can use constructor injection with #Qualifier.
class Super {
private List<String> someStrings;
public Super(private List<String> someStrings) {
this.someStrings = someStrings;
}
}
#Component
class Derived1 extends Super {
#Autowired
public Derived1(#Qualifier("listForDerived1") List<String> listForDerived1, OtherBean bean) {
super(listForDerived1);
}
}
#Component
class Derived2 extends Super {
#Autowired
public Derived1(#Qualifier("listForDerived2") List<String> listForDerived1, OtherBean bean) {
super(listForDerived2);
}
}
Also see official Spring doc: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-autowired-annotation-qualifiers