Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define different Feign client implementations based on environment

I have a Spring boot application which uses Feign to call an external web service via Eureka. I'd like to be able to run the application using a mocked out implementation of the Feign interface, so I can run the application locally without necessarily having Eureka or the external web service running. I had imagined defining a run configuration that allowed me to do this, but am struggling to get this working. The issue is that the Spring "magic" is defining a bean for the Feign interface no matter what I try.

Feign interface

@FeignClient(name = "http://foo-service")
public interface FooResource {
    @RequestMapping(value = "/doSomething", method = GET)
    String getResponse();
}

Service

public class MyService {
    private FooResource fooResource;

    ...

    public void getFoo() {
        String response = this.fooResource.getResponse();
        ...
    }
}

I tried adding a configuration class that conditionally registered a bean if the Spring profile was "local", but that was never called when I ran the application with that Spring profile:

@Configuration
public class AppConfig {
    @Bean
    @ConditionalOnProperty(prefix = "spring.profile", name = "active", havingValue="local")
    public FooResource fooResource() {
        return new FooResource() {
            @Override
            public String getResponse() {
                return "testing";
            }
        };
    }
}

At the point my service runs, the FooResource member variable in MyService is of type

HardCodedTarget(type=FoorResource, url=http://foo-service)

according to IntelliJ. This is the type that is automatically generated by the Spring Cloud Netflix framework, and so tries to actually communicate with the remote service.

Is there a way I can conditionally override the implementation of the Feign interface depending on a configuration setting?

like image 462
Daniel Kelley Avatar asked May 15 '17 11:05

Daniel Kelley


People also ask

How would you implement feign client in Microservices?

Let's implement the Feign in our project and invoke other microservices using Feign. Step 1: Select currency-conversion-service project. Step 2: Open the pom. xml and add the Feign dependency.

Can we use feign client without Eureka?

Yes you can use Feign without Ribbon, All you need to do is specify the base url in your Feign Java interface class.

What are feign clients?

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders.

What is @feignclient?

Feign is a declarative web service client that makes writing web service clients easier. To use Feign, create an interface and annotate it with @FeignClient. It has pluggable annotation support including Feign and JAX-RS annotations. Feign is a declarative web service client. It makes writing web service clients easier.

How to model the parameters of feign clients?

The parameters will be modeled using the @Param annotation: NOTE: Feign clients can be used to consume text-based HTTP APIs only, which means that they cannot handle binary data, e.g. file uploads or downloads. That's all!

How to change the global configuration of a feign client?

Good things is you can change these global configurations from property file such as connection timeout, read timeout and logger level You can also configure each feign client individually from property file using feign client name or value.

How do I use feign client in Spring Cloud?

Feign Integration with Spring Cloud With maven, we include spring-cloud-starter-openfeign artifact in our pom.xml file annotate the main class with the annotation @EnableFeignClients. Once, this is done we create an interface that has the abstract implementation of our HTTP client and annotate it with @FeignClient.


3 Answers

the solution is like below:

public interface FeignBase {
   @RequestMapping(value = "/get", method = RequestMethod.POST, headers = "Accept=application/json")
   Result get(@RequestBody Token common);
}

then define your env based interface:

@Profile("prod")
@FeignClient(name = "service.name")
public interface Feign1 extends FeignBase 
{}

@Profile("!prod")
@FeignClient(name = "service.name", url = "your url")
public interface Feign2 extends FeignBase 
{}

finally, in your service impl:

@Resource
private FeignBase feignBase;
like image 182
baron.wang Avatar answered Oct 18 '22 04:10

baron.wang


Having posted the same question on the Spring Cloud Netflix github repository, a useful answer was to use the Spring @Profile annotation.

I created an alternative entry point class that was not annotated with @EnabledFeignClients, and created a new configuration class that defined implementations for my Feign interfaces. This now allows me to run my application locally without the need to have Eureka running, or any dependent services.

like image 30
Daniel Kelley Avatar answered Oct 18 '22 02:10

Daniel Kelley


I'm using a simpler solution to avoid having multiples interfaces for a variable parameter like url.

    @FeignClient(name = "service.name", url = "${app.feign.clients.url}")
    public interface YourClient{}

application-{profile}.properties

app.feign.clients.url=http://localhost:9999
like image 23
David Canós Avatar answered Oct 18 '22 04:10

David Canós