Spring-cloud-netflix: How to Creat Feign Clients Manually

Created on 12 Nov 2016  路  2Comments  路  Source: spring-cloud/spring-cloud-netflix

I've seen the issue https://github.com/spring-cloud/spring-cloud-netflix/issues/1211 and the spring document http://cloud.spring.io/spring-cloud-static/Camden.SR2/#_creating_feign_clients_manually, but when I follow it ,it can never work. WHAT'S WRONG?

Here is my code.
https://github.com/eacdy/spring-cloud-creating-feign-manually

@Import(FeignClientsConfiguration.class)
@RestController
public class MovieController {
  private UserFeignClient userUserFeignClient;

  private UserFeignClient adminUserFeignClient;

  @Autowired
  public MovieController(ResponseEntityDecoder decoder, SpringEncoder encoder, Client client) {
    this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder)
        .requestInterceptor(new BasicAuthRequestInterceptor("user", "password1")).target(UserFeignClient.class, "http://microservice-provider-user/");
    this.adminUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder)
        .requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
        .target(UserFeignClient.class, "http://microservice-provider-user/");
  }

  @GetMapping("/user-user/{id}")
  public User findByIdUser(@PathVariable Long id) {
    return this.userUserFeignClient.findById(id);
  }

  @GetMapping("/user-admin/{id}")
  public User findByIdAdmin(@PathVariable Long id) {
    return this.adminUserFeignClient.findById(id);
  }
}

When I start the application, it can never start up. It comes this exception

Description:

Parameter 0 of constructor in com.itmuch.cloud.study.user.controller.MovieController required a bean of type 'org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder' that could not be found.

My Spring Cloud version is Camden.SR2.

documentation

Most helpful comment

@ryanjbaxter
Thanks for your help, it works.
I鈥榲e pushed the code into my github.

@Import(FeignClientsConfiguration.class)
@RestController
public class MovieController {
  private UserFeignClient userUserFeignClient;

  private UserFeignClient adminUserFeignClient;

  @Autowired
  public MovieController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
    this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
        .requestInterceptor(new BasicAuthRequestInterceptor("user", "password1")).target(UserFeignClient.class, "http://microservice-provider-user/");
    this.adminUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
        .requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
        .target(UserFeignClient.class, "http://microservice-provider-user/");
  }

  @GetMapping("/user-user/{id}")
  public User findByIdUser(@PathVariable Long id) {
    return this.userUserFeignClient.findById(id);
  }

  @GetMapping("/user-admin/{id}")
  public User findByIdAdmin(@PathVariable Long id) {
    return this.adminUserFeignClient.findById(id);
  }
}

And then I can use Spring MVC annotations.

All 2 comments

The overarching problem is an issue with my example. However I noticed a couple of other issues in your sample.

You don't need @EnableFeignClients
https://github.com/eacdy/spring-cloud-creating-feign-manually/blob/master/microservice-consumer-movie-feign-manual/src/main/java/com/itmuch/cloud/study/ConsumerMovieApplication.java#L10

And your interface should use the Feign annotations not the Spring MVC annotations

package com.itmuch.cloud.study.user.feign;

import feign.Param;
import feign.RequestLine;

import com.itmuch.cloud.study.user.entity.User;


public interface UserFeignClient {
  @RequestLine(value = "GET /{id}")
  public User findById(@Param("id") Long id);
}

To fix the problem however your RestController constructor should use the interface types for Decoder and Encoder.

package com.itmuch.cloud.study.user.controller;

import feign.Client;
import feign.Feign;
import feign.auth.BasicAuthRequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.itmuch.cloud.study.user.entity.User;
import com.itmuch.cloud.study.user.feign.UserFeignClient;


@RestController
@Import(FeignClientsConfiguration.class)
public class MovieController {
  private UserFeignClient userUserFeignClient;

  private UserFeignClient adminUserFeignClient;

  @Autowired
  public MovieController(Decoder decoder, Encoder encoder, Client client) {
    this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder)
            .requestInterceptor(new BasicAuthRequestInterceptor("user", "password1")).target(UserFeignClient.class, "http://microservice-provider-user/");
    this.adminUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder)
            .requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
            .target(UserFeignClient.class, "http://microservice-provider-user/");
  }

  @GetMapping("/user-user/{id}")
  public User findByIdUser(@PathVariable Long id) {
    return this.userUserFeignClient.findById(id);
  }

  @GetMapping("/user-admin/{id}")
  public User findByIdAdmin(@PathVariable Long id) {
    return this.adminUserFeignClient.findById(id);
  }
}

I will update the documentation.

@ryanjbaxter
Thanks for your help, it works.
I鈥榲e pushed the code into my github.

@Import(FeignClientsConfiguration.class)
@RestController
public class MovieController {
  private UserFeignClient userUserFeignClient;

  private UserFeignClient adminUserFeignClient;

  @Autowired
  public MovieController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
    this.userUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
        .requestInterceptor(new BasicAuthRequestInterceptor("user", "password1")).target(UserFeignClient.class, "http://microservice-provider-user/");
    this.adminUserFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
        .requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
        .target(UserFeignClient.class, "http://microservice-provider-user/");
  }

  @GetMapping("/user-user/{id}")
  public User findByIdUser(@PathVariable Long id) {
    return this.userUserFeignClient.findById(id);
  }

  @GetMapping("/user-admin/{id}")
  public User findByIdAdmin(@PathVariable Long id) {
    return this.adminUserFeignClient.findById(id);
  }
}

And then I can use Spring MVC annotations.

Was this page helpful?
0 / 5 - 0 ratings