web-dev-qa-db-ja.com

別のプロジェクトからのFeignClientの挿入エラー

別のプロジェクトからの偽のクライアントの自動配線に問題があります。偽のクライアントの実装は生成および挿入されていないようです。

これは私が得ているエラーです。

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'passportRestController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: private com.wstrater.service.contacts.client.ContactService com.wstrater.service.passport.server.controllers.PassportRestController.contactService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [com.wstrater.service.contacts.client.ContactService] 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)}

偽のクライアントは非常に簡単です。簡潔にするため、インポートを削除しました。

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

}

コンポーネントスキャンをプロジェクトに追加して、アプリケーションとそのコントローラーを含め、他のプロジェクトに偽のクライアントを含めました。

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

}

簡潔にするために、ほとんどのインポートが削除された残りのコントローラー。

package com.wstrater.service.passport.server.controllers;

import com.wstrater.service.contacts.client.ContactService;

@RestController
public class PassportRestController {

  @Autowired
  private ContactService contactService;

  @RequestMapping(PassportContstants.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;
  }

}

私は別のプロジェクトと別のパッケージで偽のクライアントインターフェイスを定義してみましたが、アプリケーションと同じパッケージに配置したときにのみ成功しました。これは、パッケージをスキャンに含めているにもかかわらず、コンポーネントスキャンの問題であると信じ込ませます。再利用可能な「契約」を定義するために共有プロジェクトで偽のクライアントインターフェイスを保持し、各プロジェクトがそれを使用するアプリケーションで偽のクライアントを定義するのではなく、一意のパッケージ構造を持つようにしたいと思います。

ありがとう、ウェス。

25
Wes

インターフェースの場所をFeignスキャナーに指示する必要があります。

@EnableFeignClients(basePackages = {"my.external.feign.client.package", "my.local.package"})を使用できます。

62
spencergibb

直接クラス/インターフェース名は以下のように指定できます

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

このパラメーターは、単一または複数のクラス名を受け入れます

2
Swarit Agarwal

メインクラスはパッケージ「com.abc.myservicename」にあり、メインクラス名は「myservicename.Java」でした。メインクラスで@SpringBootApplication(scanBasePackages = "com.abc")アノテーションを使用していました。

メインクラスのパッケージ名を「com.abc」に変更すると、問題が解決しました。

0
user12152065