Spring Boot cannot autowired component with abstract and interface - spring

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.

Related

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

I have a test class in Junit4 that needs to use NutrientListService.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ApplicationContext.class)
public class CalculationTests {
private NutrientListService nutrientService;
#Test
public void someTest()
Result re = Calculator.calculate(response, nutrientService)
}
I was getting a null nutrientService, so I tried to set up an ApplicationContext.
#Configuration
#ComponentScan("myservice")
#ComponentScan("myrepository")
public class ApplicationContext {
#Autowired
NutrientListService nutrientService;
}
However, I get
Error creating bean with name 'nutrientListService': Unsatisfied dependency expressed through field 'nutrientListRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'repositories.NutrientListRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
This is the service:
#Service
#Component
public class NutrientListService {
#Autowired
private NutrientListRepository repo;
}
And the repository:
#Repository
public interface NutrientListRepository extends MongoRepository<MyClass, String> {
MyClass findByID(String ID);
}
Any ideas to wire the service properly? I need to pass it for calculation as it is one of the parameters. Do I have to use an application context class or the application-context.xml (which I could not find)? What would be the least obscure way to do this? I thank you.
#Configuration
#ComponentScan("myservice")
#ComponentScan("myrepository")
public class ApplicationContext {
#Bean
NutrientListService nutrientService(){
new NutrientListService()
}
}
And then call the Bean with #Autowired
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ApplicationContext.class)
public class CalculationTests {
#Autowired
NutrientListService nutrientService
#Test
public void someTest()
Result re = Calculator.calculate(response, nutrientService)
}

spring framework : expected single matching bean but found 2

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;
}

Unsatisfied dependency during test

I have a spring boot 2.0.0 M2 application who run well.
I use autowired on constructor
#RequestMapping(value = "/rest")
#RestController
public class AddressRestController extends BaseController{
private final AddressService AddressService;
#Autowired
public AddressRestController(final AddressService AddressService) {
this.AddressService = AddressService;
}
...
}
#Service
public class AddressServiceImpl extends BaseService implements AddressService {
#Autowired
public AddressServiceImpl(final AddressRepository AddressRepository) {
this.AddressRepository = AddressRepository;
}
private final AddressRepository AddressRepository;
...
}
public interface AddressRepository extends JpaRepository<Address, Integer>, AddressRepositoryCustom {
}
#Repository
public class AddressRepositoryImpl extends SimpleJpaRepository implements AddressRepositoryCustom {
#PersistenceContext
private EntityManager em;
#Autowired
public AddressRepositoryImpl(EntityManager em) {
super(Address.class, em);
}
...
}
When i try to run a basic test
#RunWith(SpringJUnit4ClassRunner.class)
public class AddressServiceTest {
#Autowired
private AddressService service;
#MockBean
private AddressRepository restTemplate;
#Test
public void getAddress(){
MockitoAnnotations.initMocks(this);
Pageable page = PageRequest.of(0, 20);
Page<Address> pageAdr = mock(Page.class);
given(this.restTemplate.findAll(page)).willReturn(pageAdr);
Page<AddressDto> pageDto = service.getAddress(page);
}
}
I get this error
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'com.sonos.arcor.service.AddressServiceTest': Unsatisfied dependency
expressed through field 'service'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type ''com.sonos.arcor.service.AddressService'
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 i get this error.
You need to annotate the test with SpringBootTest so that spring initialize an application context
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications
#SpringBootTest
#RunWith(SpringJUnit4ClassRunner.class)
public class AddressServiceTest {
// the remaining test
}
Also you do not need MockitoAnnotations.initMocks(this);
Spring takes care of the mock handling
When [#MockBean is]used on a field, the instance of the created mock will also be
injected. Mock beans are automatically reset after each test method
see Mocking and spying beans

Spring Resource Assembler throwing NoSuchBeanDefinitionException

I am using ResourceAssemblerSupport from spring-hateoas in a spring boot Application
I have created the assembler like below:
public class MemberResourceAssembler extends ResourceAssemblerSupport<Member, MemberResource>{
public MemberResourceAssembler(Class<?> controllerClass, Class<MemberResource> resourceType) {
super(controllerClass, resourceType);
}
#Override
public MemberResource toResource(Member member) {
MemberResource memberResource=new MemberResource();
memberResource.setStatus(member.getStatus());
memberResource.setHeight(member.getHeight());
memberResource.setIs_veg(member.getIs_veg());
memberResource.setRace(member.getRace());
memberResource.setWeight(member.getWeight());
return memberResource;
}
}
And the reource class as below:
public class MemberResource extends ResourceSupport implements Serializable{
//relevant code here
}
The domain class is as below:
#Document(collection="Member")
public class Member {
//relevant code here
}
The repository class is as below:
public interface MemberRepository extends PagingAndSortingRepository<Member,Integer> {
Page<Member> findByStatusContainsIgnoreCase(#Param("q") String status, Pageable pageable);
}
Now I am trying to use in my controller as below:
#RestController
#RequestMapping("/members")
public class MemberController {
#Autowired
private MemberRepository memberRepository;
#Autowired
private MemberResourceAssembler assembler;
#RequestMapping(value = "/search", method = RequestMethod.GET)
public PagedResources<MemberResource> search(#RequestParam("status") String status, #PageableDefault Pageable pageable,
PagedResourcesAssembler<Member> pagedAssembler) {
Page<Member> members = memberRepository.findByStatusContainsIgnoreCase(status, pageable);
return pagedAssembler.toResource(members, assembler);
}
}
I am getting below exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sg.resources.MemberResourceAssembler] 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)}
Using spring-hateoas version 0.19.0.RELEASE.All the dependencies are coming through starters of Spring Boot 1.3.0.RELEASE
There is a spring boot Application class in the parent package of the Controller class.The Autowire annotation on the repository is working properly.
Your MemberResourceAssembler should be annotated as #Component to make it available for autowiring.
I added a bean definition in the Application.class which solved the issue
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public MemberResourceAssembler memberResourceAssembler() {
return new MemberResourceAssembler(MemberController.class, MemberResource.class);
}
}

How to extend #Service with spring,NoUniqueBeanDefinitionException

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

Resources