Open Feign: How to create a Service Client
We have already seen several posts on how to make clients for web services, for example here. Today we will see one more, Open Feign. The idea of this framework is to minimize the amount of code we have to develop to create a client. It does this by creating a wrapper on top of other libraries for client creation and through annotations in an interface, which will allow us to abstract from the internal logic.
Also note that Feign started as a project developed by Netflix that was part of the Spring Cloud library set, but now it has been released and can be found in standalone mode.
As we will see, the client code will be very basic and we will only have to explain a couple of annotations. The configuration and implementations that we use are where we will be able to see more the power of this library. Now, we show how a typical client for a REST service could look like.
As we can see is very simple and only with 3 annotations. And although it is practically self-explanatory we will indicate what each one is for and we will also indicate the other 3 that are not seen in this example:
- @RequestLine: It allows us to indicate the context and HTTP method to use. It allows us to indicate dynamic values with the keys.
- @Headers: It allows us to indicate a fixed or dynamic header. They can be indicated globally by placing them in the interface or specifically by placing them in the method we want.
- @Param: It allows us to associate a dynamic parameter of the URL with an input parameter to the method.
- @Body: It is indicated in the method and allows us to create a request with the format that we indicate and with the help of the parameters.
- @QueryMap and @HeaderMap: They allow us to indicate maps of key-value pairs at method parameter levels that are associated to request parameters or headers.
Once we have the definition, we are going to generate the client. As we have indicated above, another of Feign’s strong points is that it abstracts us from implementation details. But it will be during the creation of the client where we will have to decide with which other libraries we want to carry out the creation of the client. We will have several aspects to define, the most basic ones are:
- Client: Indicate with the help of which library we want to implement the client, such as OkHttp, Java 11 Http2, or Ribbon.
- Encoder and decoder of the response body: You can choose between JSON libraries such as Jackson or GSON or XML such as SAX or JAXB.
- Logs: Indicate the library with which we want to control the traces. You can choose between the default one (which will be deprecated) and SLF4J.
- Target: URL we are going to attack and declaration of the client we are going to use.
We must also take into account that depending on the options we choose to create our client we will have to indicate some dependencies or others. For this case for example we have used these. But for the next examples, we need to include other libraries.
- feign-slf4j. Which in turn needs slf4j-log4j12.
Now we will see how to do error handling and indicate the retry policy. To handle errors, we will create a class that will allow us to send the messages that we require or keep retrying depending on concrete errors. This class must implement ErrorDecoder Interface. And in the method that we overwrite, we must throw an exception. We must take into account that if we do not indicate the exception in the Web Services declaration, the client will throw an exception of the UndeclaredThrowableException type.
For the retry policy, we can do it easily by instantiating the Retryer class and indicating the maximum time to wait and the number of retries. Both configurations will be indicated at the moment of creating the client.
Another configuration that we can make is the association of Interceptors that allow us to modify all the calls that we are going to make to a certain destination. One of the most common can be the one that adds basic authentication and for that purpose, there is already a specific class, BasicAuthRequestInterceptor. But if we want to create our own interceptor we will have to start by implementing the RequestInterceptor interface.
And to use it, as in the previous cases, we will only have to add it to our configuration.
Finally, we are going to see how we can make use of Ribbon as our client implementation. This will allow us to invoke a particular Web Service or microservice through a name and not a specific IP. As the possibility of balancing between different servers with the deployed service. To do this we will have to include the corresponding dependency and configure the client as in the previous cases. But we will also have to include in the classpath a file called config.properties in which we will indicate the list of servers associated with the name of the Service we want to invoke.
And with this, we have seen some of the features of Feign. And another way to create a client of a Web Services or microservice. If you want to see the concrete example you can see it here.