The subject of this lab is the spring cloud Feign project. Feign is known as a declarative REST Client. We will familiarize ourselves with Feign by refactoring the greeting-ribbon-rest project to use Feign instead of Spring’s RestTemplate.

1. Duplicate greeting-ribbon-rest

Our starting point will be the greeting-ribbon-rest project.

  1. Make a full copy of this project, and rename the base directory. For example, here are the mac/linux instructions:

    cp -R greeting-ribbon-rest my-greeting-feign-project
  2. cd into your new project and modify the build file (pom.xml) as follows:

    1. modify the artifact id to greeting-feign

    2. likewise, modify the project name to greeting-feign

    3. add the spring-cloud-starter-feign dependency:

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

At this point, your project should compile. Verify this with the following command:

mvn clean package

Finally, load your project into an IDE (for example, Spring Tool Suite).

2. Refactoring to Feign

  1. The application’s main class is currently called GreetingRibbonRestApplication. Rename this class GreetingFeignApplication.

  2. Add the annotation @EnableFeignClients at the class level, to turn on Feign support.

  3. Delete or remove the RestTemplate bean that’s currently defined in the application class. We’ll be replacing it with a Feign client in the course of subsequent refactorings.

  4. In src/main/resources/bootstrap.yml, revise the spring.application.name property value to greeting-feign

2.1. Define a FeignClient interface for fortune-service

In a nutshell, Feign supports the mapping of Rest API calls to a Java interface. In lieu of using Spring’s RestTemplate to call fortune-service, greeting-feign will do so by means of an interface.

  1. Create a Java interface and name it FortuneServiceClient

  2. Within this interface definition, define a single method named getFortune() with no arguments, that returns a String

In order to map this method call to a REST api call against the fortune-service application, we’ll leverage the fact that Feign is integrated with Eureka, and can automatically discover the url for the fortune service from the name of the service (also known as the serviceId).

  1. Add the @FeignClient annotation at the class level. This annotation’s main argument is the name of the service we’re going to call: fortune-service.

  2. Add the @RequestMapping annotation to the method. You’ll need to specify the http method (GET) and the path to the fortune-service endpoint ("/") as arguments.

It’s interesting to point out that Feign uses the same annotation as Spring’s WebMVC: @RequestMapping. Even though WebMVC is all about handling requests, the @RequestMapping annotation is a pure description of a mapping, either from or to a method, and so it can be used in both server-side implementations (as in WebMVC) and client-side implementations (as in Feign). Among other things, this means that one doesn’t have to learn a different request mapping vocabulary, and that all of the @RequestMapping features, such as path variables, are supported.

Your resulting interface definition should resemble this:

package io.pivotal.greeting;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("fortune-service")
public interface FortuneServiceClient {

  @GetMapping(value = "/")
  String getFortune();
}

2.2. Retrofitting GreetingController

Let’s turn our attention now to the GreetingController class.

  1. Revise the implementation to inject an instance of the FortuneServiceClient interface we just created instead of the current RestTemplate instance.

  2. Now revise the implementation of getGreeting() to use fortuneServiceClient.getFortune() instead of restTemplate.getForObject(…​)

Your code should look something like this:

package io.pivotal.greeting;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class GreetingController {

  private final Logger logger = LoggerFactory.getLogger(GreetingController.class);

  private final FortuneServiceClient fortuneServiceClient;

  public GreetingController(FortuneServiceClient fortuneServiceClient) {
    this.fortuneServiceClient = fortuneServiceClient;
  }

  @RequestMapping("/")
  String getGreeting(Model model) {

    logger.debug("Adding greeting");
    model.addAttribute("msg", "Greetings!!!");

    String fortune = fortuneServiceClient.getFortune();

    logger.debug("Adding fortune");
    model.addAttribute("fortune", fortune);

    return "greeting"; // resolves to the greeting.ftl template
  }


}

Note how this revised implementation of GreetingController feels much more natural: the REST API call is completely hidden, encapsulated behind a method call.

It’s important to point out that these calls to getFortune() are automatically integrated with Ribbon as well, and the calls will load-balance across multiple instances of the fortune service.

3. Try out greeting-feign

Let’s try our greeting-feign:

  1. start config-server, service-registry, and one ore more instances of fortune-service

  2. as usual, verify in the eureka dashboard that the fortune-service is up and registered

  3. start greeting-feign

  4. in a browser, visit http://localhost:8080/ and verify that, as before, you’re getting greetings

  5. optionally, you can also verify that ribbon load balancing across multiple fortune-service instances still takes place.

There’s much more to Feign. The API is simple and clean. This library is versatile and un-opinionated. Feign can be used with a variety of underlying http client libraries, encoders and decoders, loggers, interceptors, and more. Feign today is a community-driven project. You can find out more at https://github.com/OpenFeign/feign. You might also want to check out this excellent devoxx talk on Feign by Igor Laborie.

In this lab, we’ve focused on the integration of Feign with Ribbon and Eureka, and the Spring-specific customization of the Feign library.

Congratulations! You’ve completed the lab.