Ошибка внедрения FeignClient из другого проекта
У меня возникают проблемы с авторизацияцией клиента Feign из другого проекта. Похоже, что реализация клиента Feign не генерируется и не внедряется.
Вот ошибка, которую я получаю:
org.springframework.beans.factory.BeanCreationException:
Ошибка создания бина с именем 'passportRestController': Внедрение автозависимостей не удалось; вложенное исключение org.springframework.beans.factory.BeanCreationException:
Не удалось внедрить поле: private com.wstrater.service.contacts.client.ContactService com.wstrater.service.passport.server.controllers.PassportRestController.contactService; вложенное исключение org.springframework.beans.factory.NoSuchBeanDefinitionException:
Не найдено ни одного квалифицированного бина типа [com.wstrater.service.contacts.client.ContactService] для зависимости: ожидался как минимум 1 бин, который соответствовал бы кандидату для автозависимости. Аннотации зависимости:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
Клиент Feign довольно простой. Я убрал импорты для краткости.
package com.wstrater.service.contacts.client;
@FeignClient("contact-service")
public interface ContactService {
@RequestMapping(method = RequestMethod.GET, value = ContactConstants.CONTACTS_USER_ID_PATH)
public Collection<Contact> contactsByUserId(@PathVariable("userId") String userId);
}
Я добавил компонентный скан в свой проект, чтобы включить приложение и его контроллеры, а также клиент Feign из другого проекта.
package com.wstrater.service.passport.server;
@EnableEurekaClient
@EnableFeignClients
@SpringCloudApplication
@ComponentScan({"com.wstrater.service.passport.server",
"com.wstrater.service.contacts.client"})
public class PassportServiceApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(PassportServiceApplication.class, args);
}
}
Контроллер REST, в котором большинство импортов удалены для краткости.
package com.wstrater.service.passport.server.controllers;
import com.wstrater.service.contacts.client.ContactService;
@RestController
public class PassportRestController {
@Autowired
private ContactService contactService;
@RequestMapping(PassportConstants.PASSPORT_USER_ID_PATH)
public ResponseEntity<Passport> passportByUserId(@PathVariable String userId) {
ResponseEntity<Passport> ret = null;
Collection<Contact> contacts = contactService.contactsByUserId(userId);
if (contacts == null || contacts.isEmpty()) {
ret = new ResponseEntity(HttpStatus.NOT_FOUND);
} else {
ret = ResponseEntity.ok(new Passport(contacts));
}
return ret;
}
}
Я пробовал определять интерфейс клиента Feign в разных проектах и пакетах, и добивался успеха только тогда, когда помещал его в тот же пакет, что и приложение. Это заставляет меня думать, что проблема связана со сканированием компонентов, хотя я и включил этот пакет в сканирование. Я хотел бы оставить интерфейс клиента Feign в общем проекте, чтобы определить многократно используемый "контракт", а также чтобы у каждого проекта была уникальная структура пакетов, вместо того чтобы определять клиента Feign вместе с приложением, его использующим.
Спасибо, Уэс.
5 ответ(ов)
Вы можете указать сканеру Feign, где находить интерфейсы, используя аннотацию @EnableFeignClients
. Например, вы можете сделать это следующим образом:
@EnableFeignClients(basePackages = {"my.external.feign.client.package", "my.local.package"})
Таким образом, сканер будет искать интерфейсы в указанных пакетах: как в вашем внешнем пакете, так и в локальном.
Вы можете указать имя класса или интерфейса напрямую следующим образом:
@EnableFeignClients(basePackageClasses = com.abc.xxx.client.XXFeignClient.class)
Этот параметр принимает как одно, так и несколько имен классов. Вы можете передать несколько классов, перечисляя их через запятую, например:
@EnableFeignClients(basePackageClasses = {
com.abc.xxx.client.XXFeignClient.class,
com.abc.xxx.client.YYFeignClient.class
})
Это позволяет Spring автоматически сканировать указанные классы для создания необходимых бинов.
Проблема была связана с тем, что мой главный класс находился в пакете "com.abc.myservicename", а название класса было "myservicename.java". Я использовал аннотацию @SpringBootApplication(scanBasePackages="com.abc")
в своём главном классе.
Изменение имени пакета главного класса на "com.abc" решило для меня эту проблему.
Это сработало для меня. Добавление аннотации к главному классу:
@EnableFeignClients(defaultConfiguration = {FeignBasicConfiguration.class}, basePackages = {"com.example"})
Убедитесь, что вы правильно указали базовые пакеты и конфигурацию, чтобы корректно подключить Feign-клиенты.
Спасибо за помощь. Я добавил нужный внешний пакет в аннотацию @EnableFeignClients(basePackages = {})
, но всё равно не удалось загрузить реализацию Feign-клиента.
У меня был тест контракта PACT, где я использовал внедрение бина API-клиента. Я применял аннотацию @ExtendWith(SpringExtension.class)
, что и стало причиной проблемы. После замены на @SpringBootTest
, Feign-клиент стал доступен в этом классе.
Инициализация ArrayList в одну строчку
Что значит 'synchronized'?
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?