Spring Cloud OpenFeign for Microservices Communication

Soy Phea
3 min readFeb 17, 2021

--

Introduction

In the microservices world, every small service is working together to do their own piece features own by an autonomous team.

They commonly use HTTP RESTful API, messaging, and another integration pattern. In this section, we will walk some basic on Spring Cloud OpenFeign, specific for HTTP communication.

What is Spring Cloud OpenFeign?

Spring Cloud OpenFeign is inspired by Netflix OpenFeign to build a REST client that leverages the spring feature with declarative style and Spring MVC annotation. It makes life easy for spring developers and clean.

What you have to make your spring boot project visible with Spring Cloud OpenFeign, you can the maven or Gradle dependency to your project.

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Create your own FeingClient to call downstream services:

@FeignClient(value = "Github", url = "http://localhost:9099/api"
, configuration = BookClientConfig.class
)
public interface BookClient {

@GetMapping("/books/sbn/{sbn}")
Book getBookBySbn(@PathVariable("sbn") String sbn);

@GetMapping("/books")
List<Book> allBooks();

@PostMapping("/books")
Book addNewBook(@RequestBody Book book);
}

Every FeignClient is an interface. You are also can extend with another interface.

BookClient will connect to the URL and execute the following method based on interface predefined.

Example:

@Autowire
private BookClient bookClient
bookClient.getBookBySbn("1234")

It connect to the downstream service with url http://localhost:9099/api and HTTP GET method and URI /books/sbn/1234.

GET http://localhost:9099/api/books/sbn/1234

On configuration annotation, it is a class in which BookClient will peak up for the configuration. You can use the class as the configuration or application properties for your own FeignClient. This is my example for my BookClientConfig.

public class BookClientConfig {

@Bean
Logger.Level feignLoggerLevel() {
return Level.FULL;
}
}

My BookClientConfig contains with turning the logging level for my FeignClient to be FULL. The FULL level will be logged the headers, body, and requests, and responses. It included NONE, HEADERS, BASIC and FULL.

Which beneficial for you, which would be easy for turning for debugging if you are curious to see request/response, HTTP code, etc.

Fallback with Spring Cloud OpenFeign

Spring Cloud OpenFeing gives the implementation for the fallback which necessary for implement resilience microservices.

@FeignClient(value = "Github", url = "http://127.0.0.1:9099/api"
, configuration = BookClientConfig.class,
fallback = BookCallBack.class
)

You can add a fallback into @FeignClient to provide the fallback.

@Component
public class BookCallBack implements BookClient {

@Override
public Book getBookBySbn(String sbn) {
return new Book();
}

@Override
public List<Book> allBooks() {
return Collections.singletonList(new Book());
}

@Override
public Book addNewBook(Book book) {
return null;
}
}

ErrorDecoder

In Spring Cloud OpenFeign ErrorDecoder, it is executed every error that occurred with HTTP status code, not equal 2xx. It is useful when you want to custom any exception, custom retry with RetryableException whether you want to retry when not to retry.

This is an example for MyErrorDecoder.

public class MyErrorDecoder implements ErrorDecoder {

Logger logger = LoggerFactory.getLogger(MyErrorDecoder.class);
@Override
public Exception decode(String s, Response response) {
logger.info("Running method {} with response code is {} response.request() is {}",s,response.status(),response.request());
return new RetryableException(response.status(),"Would like to retry",response.request()
.httpMethod(),null,response.request() );
return new HttpClientException("Boom!");
}
}

Adding the bean in BooClientConfig:

@Bean
ErrorDecoder errorDecoder(){
return new MyErrorDecoder();
}

Interceptors

You can add the interceptors for your use cases. The real example might be, every you want to send the request to access the downstream resource you want to add the basic authorization. We can create the bean in BookClienConfig

@Bean
@ConditionalOnProperty(value = {"authorization.username", "authorization.password"})
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(
@Value("${authorization.username}") String username,
@Value("${authorization.password}") String password) {
return new BasicAuthRequestInterceptor(username, password);
}

This bean will be created if there is authorization.username authorization.password found. We use BasicAuthRequestInterceptor for this.

If you are looking for a generic interceptor you can use RequestInterceptor. Example:

@Bean
RequestInterceptor requestInterceptor() {
return requestTemplate -> {
requestTemplate.header("UUID", UUID.randomUUID().toString());
};
}

Next article, we will look at how can we implement Retry in Spring Cloud OpenFeign and use the application.properties to configure FeignClient.

Here is the code if you want more fun.

--

--

Soy Phea
Soy Phea

Written by Soy Phea

System Design, Scalability, Spring/Java, k8s

No responses yet