Feign Clients Are Cool
Tags: webdev, java, api
Published: 2022-09-09 12:12:13

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](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html) 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.

```java
String requestParam = "?validation=" + VALIDATION_VARIABLE
String url = "http://somewebsite.com/some/api/path" + requestParam
``` 

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

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

Then formatting the string in java

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

public void someMethod() {
    String fullUrl = String.format(url, "every", "single", "request", "value")
}
```

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](https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html) with [Open Feign](https://spring.io/projects/spring-cloud-openfeign). This solution is so far what I'm happiest with! Take a look

```java
@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
    )

}
```

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](https://javadoc.io/static/io.github.openfeign/feign-core/10.12/feign/RequestInterceptor.html) 

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