15

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?

Kristoffer
  • 410
  • 2
  • 6
  • 16
  • I wouldn't be surprised if you're the first to do this. You would have to build the Feign client by hand. – spencergibb Mar 26 '15 at 20:23
  • Ah well. I guess that might be true. Would be convenient if it could work though. – Kristoffer Mar 27 '15 at 08:27
  • Why do you need to redeclare the `getResourceByIdentifier()` method? Isn't it the same as the parent interface? – Dave Syer Mar 27 '15 at 12:16
  • Yes. It's actually a mistake I included it in the example. I was tying out different permutations to see if anything would work. – Kristoffer Mar 27 '15 at 12:19
  • 1
    @Kristoffer Feign doesn't support inheritance yet. See https://github.com/Netflix/feign/pull/246 – spencergibb Jul 08 '15 at 17:45
  • @spencergibb thanks for the heads up on that. We have now moved to using RestTemplate for everything though. As we had too many practical problems with Feign – Kristoffer Jul 09 '15 at 05:39

1 Answers1

17

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 {

}
martinsefcik
  • 346
  • 9
  • 20
Alex Wittig
  • 2,800
  • 1
  • 33
  • 42
  • 1
    For anyone using this strategy in an application using Spring MVC controllers: this will add handlers for the `UserService` interface, which is probably not what you want. To work around this issue in Spring, use one of the solutions outlined here: https://github.com/spring-cloud/spring-cloud-netflix/issues/466 – Michel Apr 14 '18 at 19:12