How to call a REST service from Spring declaratively using OpenFeign?

If you are using Spring, you are probably using Rest Template provided by Spring to invoke third party REST services.

That involves some code , preparing the REST template , populating the parameters required for one of the methods exposed by the REST template and finally invoking one of its specific methods.

What if you don’t need to do anything of this at all?

What if you can call REST services declaratively without manually invoking any method.

OpenFeign allows you to do this.

Spring OpenFeign is a declarative web service client provided by Spring framework. It is used by Netflix and is particularly useful in developing microservices.

Now let’s consume a REST service with very little code using Open Feign.

Here is a REST service which returns a list of persons . I have deployed it in port 8090 in my local.

It returns a list of persons.

To consume this from a spring application , the traditional way is to use Spring REST template. (Spring framework advises to use WebClient though, a reactive , non blocking REST client , instead of REST Template as it is in maintenance mode and may be removed in later versions)

Coming back to our case , below are the steps to use Open Feign.

STEP 1: Add open feign dependency.

I added using Spring initializr along with Spring Web dependency:

Here is my pom.xml generated:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.springboot</groupId>
	<artifactId>openfeign</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>openfeign</name>
	<description>Demo project for Spring Boot Open Feign</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR4</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>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

STEP 2: Add the annotation @EnableFeignClients in your SpringBoot starter class:

package com.springboot.openfeign;

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

@SpringBootApplication
@EnableFeignClients
public class OpenfeignApplication {

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

}

STEP 3: Create an Open Feign interface:

Create an interface annotated with @FeignClient annotation. Give it a name using name attribute.

Also pass the url of the service you want to call in url attribute.

For each REST service you want to consume add a method declaration annotated with @RequestMapping in the interface.

Here is an interface I created for a GET HTTP method. This will in turn invoke the REST service I had exposed at port 8090.

package com.springboot.openfeign;

import java.util.List;

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

@FeignClient(name="personclient",url="http://localhost:8090/")
public interface PersonClient {

	
	@RequestMapping(method = RequestMethod.GET,value="/persons")
	List<Person> getPersons();
}

The value field in the @RequestMapping annotation refers to the endpoint that we are going to call deployed at localhost:8090.

Person is a class which has the fields exactly as the response returned by the REST service I want to consume.

STEP 4: Test it.

I have created a new REST service which consumes the rest service exposed at port 8090.

All it does is invoke the method which we just declared in the OpenFeign interface:

package com.springboot.openfeign;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RestConsumer {

	
	@Autowired
	private PersonClient client;
	
	@GetMapping("/getAllPersons")
	public List<Person> getAllPersons(){
		
		return client.getPersons();
	}
}

Autowire the open feign interface and call its method.

That’s it!

Consuming rest services is much easier!

We can do it declaratively instead of creating a new method for each service call.

I have provided a very simple example to explain the concept.

OpenFeign can be further customized according to our needs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s