diff --git a/spring-reactive-modules/spring-5-reactive-3/pom.xml b/spring-reactive-modules/spring-5-reactive-3/pom.xml
index 5d5bfbdc5b..d33b63e921 100644
--- a/spring-reactive-modules/spring-5-reactive-3/pom.xml
+++ b/spring-reactive-modules/spring-5-reactive-3/pom.xml
@@ -20,6 +20,14 @@
org.springframework.boot
spring-boot-starter-webflux
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
org.projectreactor
reactor-spring
@@ -35,10 +43,27 @@
reactor-test
test
+
+ org.projectlombok
+ lombok
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
1.0.1.RELEASE
+ 2021.0.4
\ No newline at end of file
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/Product.java b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/Product.java
new file mode 100644
index 0000000000..f915792a31
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/Product.java
@@ -0,0 +1,13 @@
+package com.baeldung.webclient;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Product {
+ private String title;
+ private String description;
+}
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsFeignClient.java b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsFeignClient.java
new file mode 100644
index 0000000000..d3f7f8118f
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsFeignClient.java
@@ -0,0 +1,15 @@
+package com.baeldung.webclient;
+
+import java.net.URI;
+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(value = "productsBlocking", url = "http://localhost:8080")
+public interface ProductsFeignClient {
+
+ @RequestMapping(method = RequestMethod.GET, value = "/slow-service-products", produces = "application/json")
+ List getProductsBlocking(URI baseUrl);
+}
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsSlowServiceController.java b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsSlowServiceController.java
new file mode 100644
index 0000000000..8f70c3b228
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/ProductsSlowServiceController.java
@@ -0,0 +1,21 @@
+package com.baeldung.webclient;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ProductsSlowServiceController {
+
+ @GetMapping("/slow-service-products")
+ private List getAllProducts() throws InterruptedException {
+ Thread.sleep(2000L); // delay
+ return Arrays.asList(
+ new Product("Fancy Smartphone", "A stylish phone you need"),
+ new Product("Cool Watch", "The only device you need"),
+ new Product("Smart TV", "Cristal clean images")
+ );
+ }
+}
\ No newline at end of file
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebClientApplication.java b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebClientApplication.java
new file mode 100644
index 0000000000..9e55211b24
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebClientApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.webclient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableFeignClients
+public class WebClientApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(WebClientApplication.class, args);
+ }
+}
+
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebController.java b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebController.java
new file mode 100644
index 0000000000..7ab6754d44
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/main/java/com/baeldung/webclient/WebController.java
@@ -0,0 +1,59 @@
+package com.baeldung.webclient;
+
+import java.net.URI;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import reactor.core.publisher.Flux;
+
+@Slf4j
+@RestController
+public class WebController {
+
+ private static final int DEFAULT_PORT = 8080;
+
+ public static final String SLOW_SERVICE_PRODUCTS_ENDPOINT_NAME = "/slow-service-products";
+
+ @Setter
+ private int serverPort = DEFAULT_PORT;
+
+ @Autowired
+ private ProductsFeignClient productsFeignClient;
+
+ @GetMapping("/products-blocking")
+ public List getProductsBlocking() {
+ log.info("Starting BLOCKING Controller!");
+ final URI uri = URI.create(getSlowServiceBaseUri());
+
+ List result = productsFeignClient.getProductsBlocking(uri);
+ result.forEach(product -> log.info(product.toString()));
+ log.info("Exiting BLOCKING Controller!");
+ return result;
+ }
+
+ @GetMapping(value = "/products-non-blocking", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+ public Flux getProductsNonBlocking() {
+ log.info("Starting NON-BLOCKING Controller!");
+ Flux productFlux = WebClient.create()
+ .get()
+ .uri(getSlowServiceBaseUri() + SLOW_SERVICE_PRODUCTS_ENDPOINT_NAME)
+ .retrieve()
+ .bodyToFlux(Product.class);
+
+ productFlux.subscribe(product -> log.info(product.toString()));
+ log.info("Exiting NON-BLOCKING Controller!");
+ return productFlux;
+ }
+
+ private String getSlowServiceBaseUri() {
+ return "http://localhost:" + serverPort;
+ }
+
+}
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/test/java/databuffer/DataBufferToInputStreamUnitTest.java b/spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java
similarity index 98%
rename from spring-reactive-modules/spring-5-reactive-3/src/test/java/databuffer/DataBufferToInputStreamUnitTest.java
rename to spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java
index b885919bbb..f30b4a8a3b 100644
--- a/spring-reactive-modules/spring-5-reactive-3/src/test/java/databuffer/DataBufferToInputStreamUnitTest.java
+++ b/spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/databuffer/DataBufferToInputStreamUnitTest.java
@@ -1,4 +1,4 @@
-package databuffer;
+package com.baeldung.databuffer;
import com.baeldung.databuffer.DataBufferToInputStream;
diff --git a/spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java b/spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java
new file mode 100644
index 0000000000..e401fb649d
--- /dev/null
+++ b/spring-reactive-modules/spring-5-reactive-3/src/test/java/com/baeldung/webclient/WebControllerIntegrationTest.java
@@ -0,0 +1,49 @@
+package com.baeldung.webclient;
+
+import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_CLASS;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+@DirtiesContext(classMode = BEFORE_CLASS)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = WebClientApplication.class)
+class WebControllerIntegrationTest {
+
+ @LocalServerPort
+ private int randomServerPort;
+
+ @Autowired
+ private WebTestClient testClient;
+
+ @Autowired
+ private WebController webController;
+
+ @BeforeEach
+ void setup() {
+ webController.setServerPort(randomServerPort);
+ }
+
+ @Test
+ void whenEndpointWithBlockingClientIsCalled_thenThreeProductsAreReceived() {
+ testClient.get()
+ .uri("/products-blocking")
+ .exchange()
+ .expectStatus().isOk()
+ .expectBodyList(Product.class).hasSize(3);
+ }
+
+ @Test
+ void whenEndpointWithNonBlockingClientIsCalled_thenThreeProductsAreReceived() {
+ testClient.get()
+ .uri("/products-non-blocking")
+ .exchange()
+ .expectStatus().isOk()
+ .expectBodyList(Product.class).hasSize(3);
+ }
+}
\ No newline at end of file