DEV Community

Kevin Lago
Kevin Lago

Posted on

Feign Clients Are Cool

Hi everyone! :D Hope you're doing well and taking care of yourself! Today I'd like to share why I like Feign Clients over RestTemplates for both external, and "internal" API calls!

When working with RestTemplates I've never found a pleasing way to store and organize URLs. Originally I would hard code the URL and append concatenated strings like so.

String requestParam = "?validation=" + VALIDATION_VARIABLE
String url = "http://somewebsite.com/some/api/path" + requestParam
Enter fullscreen mode Exit fullscreen mode

There are a couple reasons I can think of why you would want to avoid this! For one it becomes a security concern when handling sensitive variables such as identifiers. The second your API request has more than x request parameters it becomes a nightmare to work with. Beyond that it's just not pleasing to look at! My next approach was storing my urls and sensitive request parameters in application.properties/application.yml files like so

env:
    urls:
        full-example-url: "http://somewebsite.com/some/api/path?every=%s&single=%s&request=%s&variable=%s
Enter fullscreen mode Exit fullscreen mode

Then formatting the string in java

@Value("${env.urls.full-example-url}")
String url;

public void someMethod() {
    String fullUrl = String.format(url, "every", "single", "request", "value")
}
Enter fullscreen mode Exit fullscreen mode

Both of these approaches are terrible. The second an API changes or your requirements change it becomes very time consuming trying to figure out how you setup these URLs. I briefly explored java's built in URL object but came to the same conclusion. It's messy and annoying to work with. Even if there were a pleasing way to handle these URLs, requiring a mapper to map the String result to POJO objects didn't make me a happy camper!

Finally I decided to try using @FeignClient with Open Feign. This solution is so far what I'm happiest with! Take a look

@FeignClient(name = "example-feign-client", url = "${env.urls.example_api}", path="/api")
public interface ExampleFeignApi {

    @GetMapping(value = "/some/random/path")
    ResponseEntity<MyPOJO> getApiResponse(
        @RequestParam("sensitive_variables") String id,
        @RequestParam("whatever") Integer whatever,
        @RequestParam("lastone") String lastOne
    )

}
Enter fullscreen mode Exit fullscreen mode

With this approach the only thing I'd need to store in my properties files are the base url and any sensitive variables. Mapping the URL and API responses are handled automagically. It's very clear what's required in the request and calling this method from our java code will give us autocomplete hints! So instead of guessing what's required you're literally told what you need for it to work. On top of all of this you're able to @Bean some cool stuff like custom RequestInterceptors

Give it a try! And let me know if there's something I'm missing with these URLs! I still have a lot to learn! :D

Top comments (0)