How can I change feign client url according to property file?

Viewed 5313

I have a Feign client that send request to given url

@FeignClient(
        name = "feign-client-name",
        url = "${feign.client.url}",
        configuration = FeignClientConfiguration.class)
public interface SomeFeignClient {

    @GetMapping(SOME_GEP_MAPPING_PATH)
    Entity getEntity(String id);
}
feign:
  client:
    url: https://url-to-service.com
    token: secret_token
    internal-url: https://url-to-internal-service.com
    internal: on
   
@RequiredArgsConstructor
public class FeignClientConfiguration {

    private final FeignProperties properties;

    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            template.header(HttpHeaders.AUTHORIZATION, "Token " + properties.getToken());
            template.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
            template.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
        };
    }
}

How can I change the url for feign client depends on internal property?
I want it work in following way: if internal property has value on feign client should use internal-url value and url value in other case

UPD:
Possible solution -to use Spring Profiles.

2 Answers
  1. For all kind of environment related properties, use Spring profiles. Like for DEV env you will have dev specific properties, similarly for prod env, test env etc. More info : Using Spring Profiles

  2. When you are using Feign Client, and you have an Eureka Server, try to do the service discovery via Eureka. Pass the service name only for Feign Client that you are looking for. If your Microservice is registered in Eureka, it will find from there, no need for hard-coded URLs. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign. More Info : Spring-Cloud-OpenFeign

I have found solution without Spring profiles.
The main idea of this soultion is to use @ConditionalOnProperty annotation that prevent bean creation depends on particular property. In this case

Firstly we need to create new Interface called for example SomeFeignClient

public interface SomeFeignClient {
   Entity getEntity(String id);
}

Secondly create 2 Feign clients that will extend our interface and mark them using @ConditionalOnProperty annotation

@ConditionalOnProperty(prefix="feign.client", name="internal", havingValue="true")
@FeignClient(...your configurations here...)
public interface SomeFeignClientFirst extends SomeFeignClient {
   @Override
   Entity getEntity(String id);
}

@ConditionalOnProperty(prefix="feign.client", name="internal", havingValue="false")
@FeignClient(...your configurations here...)
public interface SomeFeignClientSecond extends SomeFeignClient {
   @Override
   Entity getEntity(String id);
}

If you want to add request interceptor for some of this feign client dont forget to mark them using @ConditionalOnBean annotation

@RequiredArgsConstructor
public class FeignClientConfiguration {

    private final FeignProperties properties;
    
    @ConditionalOnBean(SomeFeignClientFirst.class)
    @Bean
    public RequestInterceptor requestInterceptor() {
       return template -> {
           template.header(HttpHeaders.AUTHORIZATION, "Token " + properties.getToken());
           template.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
           template.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
       };
}
Related