spring-cloudnetflix-feign

Can a Spring Cloud Feign client share interface with an Spring Web Controller?


Building an endpoint and client with Spring MVC and Feign Client (with spring cloud). I had the thought that since both ends need to have the same annotations - and that they have to be pretty much in sync. Maybe I could define them in an interface and have the two ends implement that.

Testing it out I was somewhat surprised that it actually works for the Spring Web end.

But it I cannot find a way to do the same for a Feign client.

I basically have the interface:

@RequestMapping("/somebaseurl")
public interface ServiceInterface {
  @RequestMapping(value = "/resource/{identifier}", method = RequestMethod.POST)
  public SomeResource getResourceByIdentifier(String identifier);
}

And then the RestController

@RestController
public class ServiceController implements ServiceInterface {
    public SomeResource getResourceByIdentifier(@PathVariable("identifier") String identifier) {
    // Do some stuff that gets the resource
        return new SomeResource();
    }
}

And then finally the Feign Client

@FeignClient("serviceName")
public interface ServiceClient extends ServiceInterface {
}

The Feign client seems to not read the inherited annotations. So is there some other way I can accomplish the same thing? Where I can make the ServiceInterface into Feign client without annotating it directly?


Solution

  • This is possible as of Feign 8.6.0. From the Spring Cloud docs:

    Feign Inheritance Support

    Feign supports boilerplate apis via single-inheritance interfaces. This allows grouping common operations into convenient base interfaces. Together with Spring MVC you can share the same contract for your REST endpoint and Feign client.

    UserService.java

    public interface UserService {
    
        @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
        User getUser(@PathVariable("id") long id);
    }
    

    UserResource.java

    @RestController
    public class UserResource implements UserService {
    
    }
    

    UserClient.java

    @FeignClient("users")
    public interface UserClient extends UserService {
    
    }