Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
In this tutorial, we will take a look at the FeignClient and how to use it in a Spring Boot application.
FeignClient is a library for creating REST API clients in a declarative way. So, instead of manually coding clients for remote API and maybe using Springs RestTemplate we declare a client definition and the rest is generated during runtime forĀ use.
The Application
We will build a small command line app, which simulates a full test for our previously created Kanban API. The sample app will create a new user, logs in, retrieves all boards and unregisters the user again. It captures the most common use case (POST, GET, DELETE +Ā AuthN)
Pre-requisites
In this tutorial, we are going to use our Kanban API tutorial project. The RESTful API is showcased on Kanban backend, and we will use the running default implementation.
I will cover the endpoints as far as they are related to this tutorial in the corresponding sections. For a full API doc, seeĀ here.
The Kanban API was a tutorial I run on the Learnletter, and you can find all the pieces in theĀ blog.
Adding Dependencies
We use Maven for this tutorial. As we do not want to mess with version numbers, the easiest way is to include the Spring Cloud setup in the dependencyManagement in the MavenĀ POM.
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>
Now, we can add the dependency to Feign with a classical Spring BootĀ starter:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
FeignClient Basics
The Feign client uses a declarative approach for accessing the API. To use it, we must first enable the Spring Cloud support for it on our Spring Boot Application with the @EnableFeignClients annotation at the class level on a @Configuration class.
@SpringBootApplication@EnableFeignClients public class FeignIntroductionApplication implements ApplicationRunner { //omitted }
Next step is to declare an interface for accessing our API. We name it KanbanClient as it will provide the methods for calling our remoteĀ API.
@FeignClient(name="KanbanClient", url= "https://kanbanbackend.herokuapp.com/") public interface KanbanClient { }
To turn it into a Feign client, we must set the @FeignClient annotation on the interface and give it a name with the name attribute and also set the remote URL with the url attribute. SpEL is supported here so we could externalize the values to property files. Instead of the URL, we could also use service discovery using Eureka here. However, that is out of scope for this tutorial.
To define a remote call, we must declare a method for that and use some annotations from Spring MVC, which are typically used on @Controller on the server side. They act the same, just on the client sideĀ now.
So, letās start with adding functionality.
Making a POSTĀ call
Adding the @PostMapping annotation on a method and passing a parameter in it, will turn the method into a POST call. In the annotation, we provide the endpoint relative to the URL we set on the @FeignClient annotation.
@PostMapping(value = "/register") String registerUser(User user);
User is a simple POJO with a username and password field. Feign, and Spring will automatically transform it intoĀ JSON.
Making a GETĀ call
The same principle, but we use the @GetMapping on the method. We also send the authentication header. The API uses X-Auth-Token.
@GetMapping("/boards")List<Board> listBoards( @RequestHeader("X-Auth-Token") String authHeader);
The /boards endpoint will return a list of all Kanban boards of the user. Board is the POJO for that and contains only id andĀ name.
Making a PUTĀ Call
Same again, just with a @PutMapping annotation thisĀ time.
@PutMapping("/board/{id}")Board changeBoard( @RequestHeader("X-Auth-Token") String authHeader, @PathVariable("id") Long id, Board board);
We can change the name of a board by making a PUT to the endpoint of that board (/board/{id}). FOr the path variable see section Making Calls with Variables below.
Making a DELETEĀ Call
Kind of boring, but it looks the same as the other, just with a @DeleteMapping annotation.
@DeleteMapping("/unregister")ResponseEntity<Void> unregisterUser( @RequestHeader("X-Auth-Token") String authToken, Confirmation user);
This endpoint requires a Confirmation object with the userās password to delete the account and will also just return a 200 if successful.
Making Calls with Variables
If our endpoint requires a variable based on the entity like ids, we can use the @PathVariable annotation on a method parameter. It behaves the same as with Spring MVC @Controllers.
The defined variable can then be used in the endpoint declaration on the @PutMapping( like:
@PutMapping("/board/{id}") Board changeBoard( @RequestHeader("X-Auth-Token") String authHeader, @PathVariable("id") Long id, Board board);
Call with Authentication
We will use the login endpoint for this. It requires the user credentials send as basic auth and will return a token for further authentication.
@PostMapping("/login")ResponseEntity<Void> loginUser( @RequestHeader("Authorization") String authHeader);
The first way to pass additional information as header down is to add a method parameter with the @RequestHeader annotation on it. The value of the parameter will be set as the value of the HTTP header defined in the annotation.
In the case of authentication, it is the Authorization header. As a value, we give it the Basic auth encodedĀ string.
In subsequent calls for the Kanban API, we will use the X-Auth-Token header with aĀ token.
Response headers canāt be returned directly as the method return value, but we can use Springās ResponseEntity, which is a responseĀ wrapper.
When we call the /login endpoint successfully, it will return the auth token in a response header. The method will lookĀ like:
@PostMapping("/login")ResponseEntity<Void> loginUser( @RequestHeader("Authorization") String authHeader);
The Void as a parametrized type is needed as our endpoint does not return anything in the responseĀ body.
We use Spring Session in the Kanban API, so the auth tokens are exchanged via the X-Auth-Token header.
To retrieve the value weĀ call:
String token = response.getHeaders().getFirst("X-Auth-Token");
response is of type ResponseEntity.
Authentication Alternative
We can always pass down authentication headers using the @RequestHeader annotation on each method. However, there is also an alternative way to specify that globally.
Like Spring MVC, Feign has an interceptor concept, which can be used to do specific stuff before a remote call. The entry point is the RequestInterceptor interface.
With Spring we just need to provide a Bean implementing that particular interface to the Spring context, and it will be automatically pickedĀ up.
Example:
@Bean AuthInterceptor authFeign() { return new AuthInterceptor(); }
class AuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { template.header("Authorization", "<your token>"); }}
Our interceptor is a Spring Bean, and thus we can use the power of Spring and externalize the authN info into properties or even retrieve it from a session scoped bean were we keep the information on a per-userĀ basis.
Using the FeignClient
Now, we can inject the KanbanClient into our code like any other Spring Bean. On startup, Spring Cloud will set up the Feign client for us and give us a regular Spring Proxy so we can simply start working with the remoteĀ end.
Our FinalĀ Client
Our client using Feign looks like that in theĀ end:
@FeignClient(name="KanbanClient", url= "https://kanbanbackend.herokuapp.com/")public interface KanbanClient {
@PostMapping(value = "/register") String registerUser(User user);
@DeleteMapping("/unregister") ResponseEntity<Void> unregisterUser( @RequestHeader("X-Auth-Token") String authToken, Confirmation user );
@PostMapping("/login") ResponseEntity<Void> loginUser( @RequestHeader("Authorization") String authHeader );
@GetMapping("/boards") List<Board> listBoards( @RequestHeader("X-Auth-Token") String authHeader );
@PostMapping("/boards") Board createBoard( @RequestHeader("X-Auth-Token") String authHeader, Board board );
@PutMapping("/board/{id}") Board changeBoard( @RequestHeader("X-Auth-Token") String authHeader, @PathVariable("id") Long id, Board board );}
The SampleĀ App
The full working sample is onĀ GitHub.
It will register a new user, log in, creates a board, change the boardās name, lists all boards and then unregisters the user at theĀ end.
Originally published at codeboje.de.
Getting Started with Feign Client in Spring was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.