Search code examples
spring-bootspring-cloud-netflixspring-cloud-feignnetflix-ribbonfeign

Can I dynamic create a Feign Client or create an instance with a different name


I've defined an REST interface that has a different Spring Boot Application implementation using different spring.application.name (spring.application.name can not be the same in my business).

How can I only define a Feign Client, and can access all the SpringBootApplication REST Services?

SpringBootApplication A(spring.application.name=A) and B(spring.application.name=) has this RestService:

@RestController
@RequestMapping(value = "/${spring.application.name}")
public class FeignRestService {

    @Autowired
    Environment env;

    @RequestMapping(path = "/feign")
    public String feign() {
        return env.getProperty("server.port");
    }
}

another SpringBootApplication C:

@FeignClient(name="SpringApplication A or B")
public interface FeignClientService {

    @RequestMapping(path = "/feign")
    public String feign();
}

In SpringBootApplication C, I want to use a FeignClientService to access A and B. Do you have any idea?


Solution

  • Yes you can create a Feign client and re-use it for as many calls to different named services in the Eureka directory (you tagged the question with spring-cloud-netflix) as you want. Here's an example of how you do it:

    @Component
    public class DynamicFeignClient {
    
      interface MyCall {
        @RequestMapping(value = "/rest-service", method = GET)
        void callService();
      }
    
      FeignClientBuilder feignClientBuilder;
    
      public DynamicFeignClient(@Autowired ApplicationContext appContext) {
        this.feignClientBuilder = new FeignClientBuilder(appContext);
      }
    
      /*
       * Dynamically call a service registered in the directory.
       */
    
      public void doCall(String serviceId) {
    
        // create a feign client
    
        MyCall fc =
            this.feignClientBuilder.forType(MyCall.class, serviceId).build();
    
        // make the call
    
        fc.callService();
      }
    }
    

    Adjust the call interface to suit your requirements and then you can inject and use a DynamicFeignClient instance into the bean where you need to use it.

    We've been using this approach in production for months now to interrogate dozens of different services for stuff like version information and other useful runtime actuator data.