0

Ошибка внедрения FeignClient из другого проекта

104

У меня возникают проблемы с авторизацияцией клиента 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 ответ(ов)

1

Вы можете указать сканеру Feign, где находить интерфейсы, используя аннотацию @EnableFeignClients. Например, вы можете сделать это следующим образом:

@EnableFeignClients(basePackages = {"my.external.feign.client.package", "my.local.package"})

Таким образом, сканер будет искать интерфейсы в указанных пакетах: как в вашем внешнем пакете, так и в локальном.

0

Вы можете указать имя класса или интерфейса напрямую следующим образом:

@EnableFeignClients(basePackageClasses = com.abc.xxx.client.XXFeignClient.class)

Этот параметр принимает как одно, так и несколько имен классов. Вы можете передать несколько классов, перечисляя их через запятую, например:

@EnableFeignClients(basePackageClasses = { 
    com.abc.xxx.client.XXFeignClient.class, 
    com.abc.xxx.client.YYFeignClient.class 
})

Это позволяет Spring автоматически сканировать указанные классы для создания необходимых бинов.

0

Проблема была связана с тем, что мой главный класс находился в пакете "com.abc.myservicename", а название класса было "myservicename.java". Я использовал аннотацию @SpringBootApplication(scanBasePackages="com.abc") в своём главном классе.

Изменение имени пакета главного класса на "com.abc" решило для меня эту проблему.

0

Это сработало для меня. Добавление аннотации к главному классу:

@EnableFeignClients(defaultConfiguration = {FeignBasicConfiguration.class}, basePackages = {"com.example"})

Убедитесь, что вы правильно указали базовые пакеты и конфигурацию, чтобы корректно подключить Feign-клиенты.

0

Спасибо за помощь. Я добавил нужный внешний пакет в аннотацию @EnableFeignClients(basePackages = {}), но всё равно не удалось загрузить реализацию Feign-клиента.

У меня был тест контракта PACT, где я использовал внедрение бина API-клиента. Я применял аннотацию @ExtendWith(SpringExtension.class), что и стало причиной проблемы. После замены на @SpringBootTest, Feign-клиент стал доступен в этом классе.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь