3

I have a main SpringBootApplication class here:

package com.example.springproj;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

@RestController class here:

package com.example.springproj.controller;

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("RefDataServiceImpl")
    private RefDataService refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        // etc
    }
}

The controller autowires this interface:

package com.example.springproj.service;

public interface RefDataService {

    Configuration getConfiguration(String param);
}

Which is implemented by this class:

package com.example.springproj.services;
@Service
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        // etc
    }
}

But when I run the App.java file, I get this

***************************
APPLICATION FAILED TO START
***************************

Description:

Field refDataService in com.citi.icrm.risk.springproj.controller.RefDataController required a bean of type 'com.citi.icrm.risk.springproj.service.RefDataService' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)
    - @org.springframework.beans.factory.annotation.Qualifier(value=RefDataServiceImpl)


Action:

Consider defining a bean of type 'com.citi.icrm.risk.springproj.service.RefDataService' in your configuration.

I'm reasonably sure that this auto-wiring should work, and I'm not sure how to go about configuring this bean in a Spring boot app. What am I doing wrong?

EDIT: Things I've already tried include:

Removing all of the @Qualifier annotations

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    private RefDataServiceImpl refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        System.err.println("testing.");
        return new ResponseEntity<Configuration>(refDataService.getConfiguration("EEMS_USER_DETAIL_URL"), HttpStatus.OK);
    }
}
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        try {
            return config.getConfiguration(param, environment);
        } catch (Exception e) {
            e.printStackTrace();
            throw (RuntimeException) new RuntimeException().initCause(e);
        }
    }
}

Changing the bean names to match convention

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("refDataServiceImpl")
    private RefDataService refDataService;

    @GetMapping(path = {"/refdata"}, produces = {"application/json"})
    public ResponseEntity<Configuration> getRefData() {
        System.err.println("testing.");
        return new ResponseEntity<Configuration>(refDataService.getConfiguration("EEMS_USER_DETAIL_URL"), HttpStatus.OK);
    }
}
@Service("refDataServiceImpl")
public class RefDataServiceImpl implements RefDataService {

    @Autowired
    private ConfigRepository config;

    @Value("${ENV}")
    private String environment;

    @Override
    public Configuration getConfiguration(String param) {
        try {
            return config.getConfiguration(param, environment);
        } catch (Exception e) {
            e.printStackTrace();
            throw (RuntimeException) new RuntimeException().initCause(e);
        }
    }
}

For reference, the files fall into the app's package structure like so:

com.example.springproj
-> com.example.springproj.controller
--> RefDataController
-> com.example.springproj.services
--> RefDataService
-> com.exampple.springproj.services.impl
---> RefDataServiceImpl

Here's the folder structure, since some people have asked:

enter image description here

4 Answers4

5

Firstly, you don't need @Qualifier("RefDataServiceImpl") if you have only one implementation of the RefDataService interface. You just need

@Autowired
private RefDataService refDataService;

Secondly, the name of a bean generated on a class name but starts with a lowercase letter. In your example, the name of bean will look like refDataServiceImpl. So, you can autowired this bean like below

@Autowired
@Qualifier("refDataServiceImpl")
private RefDataService refDataService;

Thirdly, you can specify the name of bean

@Service("youBeanName")
public class RefDataServiceImpl implements RefDataService

and then autowired this bean by the name in you controller, for example

@RestController
@Api("Sample")
public class RefDataController {

    @Autowired
    @Qualifier("youBeanName")
    private RefDataService refDataService;

    //....
}
Mykola Shorobura
  • 697
  • 6
  • 12
1

Change the @Service annotation on the RefDataServiceImpl class as follows:

@Service("RefDataServiceImpl")
public class RefDataServiceImpl implements RefDataService

The @Qualifier name in the autowired service does not match a bean in your spring configuration. The default naming convention is the full path of the class. Because of this, the name that Spring is probably using in your config for the RefDataServiceImpl service is this: "com.example.springproj.services.RefDataServiceImpl".

Added: This page might be a good read: https://www.baeldung.com/spring-qualifier-annotation.

Attempt Two: Try this

@Service
@Qualifier("RefDataServiceImpl")
@Service("RefDataServiceImpl")
public class RefDataServiceImpl implements RefDataService
DwB
  • 37,124
  • 11
  • 56
  • 82
0

I fixed the issue by putting RefDataServiceImpl in the same package as RefDataService.Before this I was keeping it in a sub-folder to the main services package. I'm still certain that I should be able to make this work with an implementation sub-folder, but this works as a solution for now.

0

I ran into this same issue while trying to implement a class with a database query. Adding @Repository to the top of the implemented class solved my problem.

timotaoh
  • 312
  • 5
  • 11