Declarative REST Client Feign and Spring Boot for communication between Microservices

Using Declarative REST Client Feign and Spring Boot to communicate between Microservices

Feign is a declarative web service client developed by Netflix to make writing Rest web service clients easier comparing to the old way. To use Feign we only have to create an interface and annotate it and that's it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud integrates Ribbon and Eureka to provide a load balanced http client when using Feign.

In this tutorial we are going to create Spring Cloud OpenFeign declarative web service client using a Spring Boot microservices application. The example illustrate how the commucation between two microservices is done using Feign. We will create an app that calculate multiplication of a coefficient and a value given by the end-user.

REST Client Feign and Spring Boot Schema

1 Microservice To be called by Feign

The following microservice has only one end-point which is "/calculator/coefficient/{value}" that get the value from the link and multiply it by the coefficient readed from the properties. In order to externalize configuration read this article: Spring Cloud Config Server and Client.

spring.application.name=microservice2
server.port=8100
app.coefficient=40

package com.yamicode.microservice2.rest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("calculator")
public class CalculatorRest {

    @Value("${app.coefficient}")
    private int coefficient;

    @GetMapping("coefficient/{value}")
    public Map sum(@PathVariable int value){
        Map result = new HashMap();
        result.put("value", coefficient*value);
        return result;
    }
}

2 REST Client Feign

package com.yamicode.microservice1.rest.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.Map;

@FeignClient(name = "microservice2", url = "localhost:8100/calculator")
@Component
public interface FeignClientApiGateWay {

    //GET example
    @RequestMapping(method = RequestMethod.GET, value = "/coefficient/{value}", consumes = "application/json")
    Map calculate(@PathVariable("value") int value);

    //Post example
//    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
//    Store update(@PathVariable("storeId") Long storeId, Store store);
}


package com.yamicode.microservice1.rest;

import com.yamicode.microservice1.rest.feign.FeignClientApiGateWay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("calculator")
public class CalculatorRest {

    @Autowired
    private FeignClientApiGateWay feignClientApiGateWay;

    @GetMapping("coefficient/{value}")
    public Map sum(@PathVariable int value){
        return feignClientApiGateWay.calculate(value);
    }
}

spring.application.name=microservice1
server.port=8000
package com.yamicode.microservice1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients("")
public class Microservice1Application {

	public static void main(String[] args) {
		SpringApplication.run(Microservice1Application.class, args);
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<project>
	<!--Rest-->
	<properties>
		<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

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

	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<!--Rest-->

</project>

3 REST Client Feign Result

REST Client Feign and Spring Boot Microservices Testing