Wednesday, 10 June 2020

What is Feign Client and How to use it?


Feign client what does it mean and what it exactly does and compared to the rest template how does it outstands itself and make flexible for the developers will be seen in this tutorial.


Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations.Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates Ribbon and Eureka to provide a load-balanced HTTP client when using Feign.


This Feign client internally creates the rest template and call the corresponding service.
One of the advantages of using Feign over RestTemplate is that, we do not need to write any implementation to call the other services. So there is no need to write any unit test as there is no code to test in the first place. However, it is advised that we write Integration tests.


There are also certain advantages such as Feign integrates with Ribbon and Eureka Automatically. Feign provides a very easy way to call RESTful services. we can also use Eureka Client ID instead of the URL and then URLs are not hardcoded.


We can see step by step procedure of calling the rest service using the feign client.
1. Download the Spring war project from the https://start.spring.io/
2. Add the following dependency.

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

3. Create an Interface and add the methods need to be invoked.
EmployeeClient.java

package com.example.demo;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
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.RequestMethod;
@FeignClient(value="employees",url = "http://localhost:7010/employees/")

public interface EmployeeClient {

@RequestMapping(method = RequestMethod.GET, value = "/all")
Employees getEmployees();

@GetMapping(value = "/employee/{id}")
List<Employee> getIdEmployees(@PathVariable(name= "id") Integer empId);

}

Here @FeignClient(value="employees",url = "http://localhost:7010/employees/")
Value is the logical name of the application which needs to be invoked. You can also mention the url in some cases this is the base url of the application.
getIdEmployees(Interger empId) is the method defined in my service class. @GetMapping is the path of the service in the class. Once this done next steps is to enable the Feign Client and call it through the controller.


4. DemoApplication.java
package com.example.demo;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;


@SpringBootApplication
@EnableFeignClients
@RequestMapping(path = "/feign")
public class DemoApplication {

@Autowired
private EmployeeClient employeeDao;

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

@GetMapping(path = "/", produces = "application/json")
public Employees getEmployees() {
System.out.println("Got**********"+employeeDao.getEmployees());
return employeeDao.getEmployees();
}

@GetMapping(path = "/employee/{id}", produces = "application/json")
public ResponseEntity<List<Employee>> getIdEmployees(@PathVariable Integer id) {
System.out.println("Got Id" + id);
List<Employee> employees = employeeDao.getIdEmployees(id);
System.out.println("Got Response as "+ employees);
return new ResponseEntity<List<Employee>>(employees, HttpStatus.OK);
}

}


Here with the annotation @EnableFeignClients we have enabled the feign client. Inject the Interface here and call the corresponding method. You can see the getIdEmployees method above for reference.

Now in the Service Layer or Service Needs to be called.

5. EmployeeController.java

@RestController
@RequestMapping(path = "/employees")
public class EmployeeController
{
@Autowired
private EmployeeDAO employeeDao;

@GetMapping(path="/all", produces = "application/json")
public Employees getEmployees()
{
return employeeDao.getAllEmployees();
}

@GetMapping(path="/employee/{id}", produces = "application/json")
public List<Employee> getIdEmployees(@PathVariable Integer id)
{
System.out.println("Called GetIdEmployee>>>>>"+id);
return employeeDao.getEmployeeId(id);
}
}



6. EmployeeDAO.java


@Repository
public class EmployeeDAO {
private static Employees list = new Employees();

static {
list.getEmployeeList().add(new Employee(1, "Syed", "rizwan", "syed@gmail.com"));
list.getEmployeeList().add(new Employee(2, "Ghouse", "basha", "ghouse@gmail.com"));
list.getEmployeeList().add(new Employee(3, "Shahin", "Kameron", "shahin@gmail.com"));
}

public Employees getAllEmployees() {
return list;
}

public void addEmployee(Employee employee) {
list.getEmployeeList().add(employee);
}

public List<Employee> getEmployeeId(int id) {
System.out.println("********* Id" + id);
Map<Integer, List<Employee>> idMap = list.getEmployeeList().stream().filter(emp -> emp.getId().equals(id))
.collect(Collectors.groupingBy(Employee::getId));
System.out.println("********* Map" + idMap);
return idMap.get(id);

}
}



Make Sure you create this employee pojo in both applications. Happy Learning !!! 

No comments:
Write comments