diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml
new file mode 100644
index 0000000000..002a333749
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ com.baeldung.cloud
+ openfeign
+ 0.0.1-SNAPSHOT
+ openfeign
+ OpenFeign project for Spring Boot
+
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+ 2.0.1.RELEASE
+ Finchley.SR2
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ io.github.openfeign
+ feign-okhttp
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java
new file mode 100644
index 0000000000..c7f07f6667
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java
@@ -0,0 +1,16 @@
+package com.baeldung.cloud.openfeign;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableFeignClients
+public class ExampleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ExampleApplication.class, args);
+ }
+
+}
+
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java
new file mode 100644
index 0000000000..bdbe6efeeb
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java
@@ -0,0 +1,25 @@
+package com.baeldung.cloud.openfeign.client;
+
+import com.baeldung.cloud.openfeign.config.ClientConfiguration;
+import com.baeldung.cloud.openfeign.hystrix.JSONPlaceHolderFallback;
+import com.baeldung.cloud.openfeign.model.Post;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+@FeignClient(value = "jplaceholder",
+ url = "https://jsonplaceholder.typicode.com/",
+ configuration = ClientConfiguration.class,
+ fallback = JSONPlaceHolderFallback.class)
+public interface JSONPlaceHolderClient {
+
+ @RequestMapping(method = RequestMethod.GET, value = "/posts")
+ List getPosts();
+
+
+ @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
+ Post getPostById(@PathVariable("postId") Long postId);
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java
new file mode 100644
index 0000000000..0b16134e92
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java
@@ -0,0 +1,37 @@
+package com.baeldung.cloud.openfeign.config;
+
+import feign.Logger;
+import feign.RequestInterceptor;
+import feign.codec.ErrorDecoder;
+import feign.okhttp.OkHttpClient;
+import org.apache.http.entity.ContentType;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ClientConfiguration {
+
+ @Bean
+ public Logger.Level feignLoggerLevel() {
+ return Logger.Level.FULL;
+ }
+
+ @Bean
+ public ErrorDecoder errorDecoder() {
+ return new ErrorDecoder.Default();
+ }
+
+ @Bean
+ public OkHttpClient client() {
+ return new OkHttpClient();
+ }
+
+ @Bean
+ public RequestInterceptor requestInterceptor() {
+ return requestTemplate -> {
+ requestTemplate.header("user", "ajeje");
+ requestTemplate.header("password", "brazof");
+ requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
+ };
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java
new file mode 100644
index 0000000000..4d32cf083f
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java
@@ -0,0 +1,21 @@
+package com.baeldung.cloud.openfeign.config;
+
+import com.baeldung.cloud.openfeign.exception.BadRequestException;
+import com.baeldung.cloud.openfeign.exception.NotFoundException;
+import feign.Response;
+import feign.codec.ErrorDecoder;
+
+public class CustomErrorDecoder implements ErrorDecoder {
+ @Override
+ public Exception decode(String methodKey, Response response) {
+
+ switch (response.status()){
+ case 400:
+ return new BadRequestException();
+ case 404:
+ return new NotFoundException();
+ default:
+ return new Exception("Generic error");
+ }
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java
new file mode 100644
index 0000000000..50200957ad
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java
@@ -0,0 +1,21 @@
+package com.baeldung.cloud.openfeign.exception;
+
+public class BadRequestException extends Exception {
+
+ public BadRequestException() {
+ }
+
+ public BadRequestException(String message) {
+ super(message);
+ }
+
+ public BadRequestException(Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public String toString() {
+ return "BadRequestException: "+getMessage();
+ }
+
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java
new file mode 100644
index 0000000000..28d0e95e9a
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java
@@ -0,0 +1,21 @@
+package com.baeldung.cloud.openfeign.exception;
+
+public class NotFoundException extends Exception {
+
+ public NotFoundException() {
+ }
+
+ public NotFoundException(String message) {
+ super(message);
+ }
+
+ public NotFoundException(Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public String toString() {
+ return "NotFoundException: "+getMessage();
+ }
+
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java
new file mode 100644
index 0000000000..1aa3112320
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java
@@ -0,0 +1,22 @@
+package com.baeldung.cloud.openfeign.hystrix;
+
+import com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient;
+import com.baeldung.cloud.openfeign.model.Post;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+
+@Component
+public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {
+
+ @Override
+ public List getPosts() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Post getPostById(Long postId) {
+ return null;
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java
new file mode 100644
index 0000000000..cab9629653
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java
@@ -0,0 +1,41 @@
+package com.baeldung.cloud.openfeign.model;
+
+public class Post {
+
+ private String userId;
+ private Long id;
+ private String title;
+ private String body;
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java
new file mode 100644
index 0000000000..16e9b1dbde
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java
@@ -0,0 +1,12 @@
+package com.baeldung.cloud.openfeign.service;
+
+import com.baeldung.cloud.openfeign.model.Post;
+
+import java.util.List;
+
+public interface JSONPlaceHolderService {
+
+ List getPosts();
+
+ Post getPostById(Long id);
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java
new file mode 100644
index 0000000000..30348db3c2
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java
@@ -0,0 +1,26 @@
+package com.baeldung.cloud.openfeign.service.impl;
+
+import com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient;
+import com.baeldung.cloud.openfeign.model.Post;
+import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class JSONPlaceHolderServiceImpl implements JSONPlaceHolderService {
+
+ @Autowired
+ private JSONPlaceHolderClient jsonPlaceHolderClient;
+
+ @Override
+ public List getPosts() {
+ return jsonPlaceHolderClient.getPosts();
+ }
+
+ @Override
+ public Post getPostById(Long id) {
+ return jsonPlaceHolderClient.getPostById(id);
+ }
+}
diff --git a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties
new file mode 100644
index 0000000000..41bbbde2c3
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+spring.application.name= openfeign
+logging.level.com.baeldung.cloud.openfeign.client: DEBUG
+feign.hystrix.enabled=true
diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java
new file mode 100644
index 0000000000..72d2baa5d7
--- /dev/null
+++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.cloud.openfeign;
+
+import com.baeldung.cloud.openfeign.model.Post;
+import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class OpenfeignUnitTest {
+
+ @Autowired
+ private JSONPlaceHolderService jsonPlaceHolderService;
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+
+ @Test
+ public void whenGetPosts_thenListPostSizeGreaterThanZero() {
+
+ List posts = jsonPlaceHolderService.getPosts();
+
+ assertFalse(posts.isEmpty());
+ }
+
+ @Test
+ public void whenGetPostWithId_thenPostExist() {
+
+ Post post = jsonPlaceHolderService.getPostById(1L);
+
+ assertNotNull(post);
+ }
+
+}