Interview

10 WebFlux Interview Questions and Answers

Prepare for your next interview with our comprehensive guide on WebFlux, covering core concepts and practical applications in reactive web development.

WebFlux is a reactive web framework in the Spring ecosystem, designed to handle asynchronous and non-blocking operations with ease. It leverages the power of Project Reactor to provide a more efficient way to manage high-throughput and low-latency web applications. WebFlux is particularly well-suited for modern microservices architectures and real-time data streaming applications, making it a valuable skill for developers working in these areas.

This article offers a curated selection of WebFlux interview questions and answers to help you prepare effectively. By familiarizing yourself with these questions, you will gain a deeper understanding of WebFlux’s core concepts and practical applications, enhancing your ability to tackle technical challenges in your upcoming interviews.

WebFlux Interview Questions and Answers

1. Describe the role of Mono and Flux.

In WebFlux, Mono and Flux are the primary reactive types provided by the Reactor library for handling asynchronous data sequences.

  • Mono represents a single or empty result, suitable for zero or one item emissions.
  • Flux represents a sequence of 0 to N items, used for multiple item emissions.

These types are fundamental for building non-blocking, reactive applications, allowing for the composition of asynchronous logic in a declarative manner.

Example:

import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;

public class WebFluxExample {
    public static void main(String[] args) {
        Mono<String> mono = Mono.just("Hello, Mono!");
        mono.subscribe(System.out::println);

        Flux<String> flux = Flux.just("Hello", "Flux", "World");
        flux.subscribe(System.out::println);
    }
}

2. How would you handle backpressure?

Backpressure in WebFlux can be managed using strategies from the Reactive Streams specification, such as onBackpressureBuffer, onBackpressureDrop, or onBackpressureLatest.

Example:

Flux<Integer> flux = Flux.range(1, 100)
    .onBackpressureBuffer(10, i -> System.out.println("Dropped: " + i))
    .doOnNext(i -> {
        try {
            Thread.sleep(50); // Simulate slow consumer
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });

flux.subscribe(System.out::println);

Here, onBackpressureBuffer buffers up to 10 items and drops any additional ones, printing a message when an item is dropped. This manages the data consumption rate and prevents resource exhaustion.

3. What is the difference between flatMap and map in the context of Mono and Flux?

In WebFlux, map and flatMap transform sequences differently.

  • map: Applies a synchronous function to each element, resulting in a new Mono or Flux with transformed elements.
  • flatMap: Applies an asynchronous function returning another Mono or Flux, flattening the resulting sequences.

Example:

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class WebFluxExample {
    public static void main(String[] args) {
        // Using map
        Flux<Integer> flux = Flux.just(1, 2, 3)
            .map(i -> i * 2);
        flux.subscribe(System.out::println); // Outputs: 2, 4, 6

        // Using flatMap
        Flux<Integer> flatMappedFlux = Flux.just(1, 2, 3)
            .flatMap(i -> Mono.just(i * 2));
        flatMappedFlux.subscribe(System.out::println); // Outputs: 2, 4, 6
    }
}

map applies a synchronous transformation, while flatMap applies an asynchronous one, flattening the results into a single Flux.

4. How do you implement error handling in a stream?

Error handling in a WebFlux stream can be done using operators like onErrorResume, onErrorReturn, and doOnError. These operators define fallback logic, return default values, or perform side effects when an error occurs.

Example:

import reactor.core.publisher.Flux;

public class ErrorHandlingExample {
    public static void main(String[] args) {
        Flux<String> flux = Flux.just("1", "2", "a", "3")
            .map(Integer::parseInt)
            .onErrorResume(e -> {
                System.out.println("Error occurred: " + e.getMessage());
                return Flux.just(-1);
            });

        flux.subscribe(System.out.println);
    }
}

Here, onErrorResume handles any NumberFormatException by emitting a fallback value of -1 and printing the error message.

5. Describe the role of Schedulers and how you would use them.

Schedulers in WebFlux control the execution context of reactive streams, specifying which thread or thread pool should execute a part of the pipeline. This optimizes performance and ensures that blocking operations do not interfere with non-blocking ones.

Example:

import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

public class SchedulerExample {
    public static void main(String[] args) {
        Mono.fromCallable(() -> {
            // Simulate a blocking operation
            Thread.sleep(1000);
            return "Result";
        })
        .subscribeOn(Schedulers.boundedElastic())
        .doOnNext(result -> System.out.println("Received: " + result))
        .block();
    }
}

In this example, subscribeOn(Schedulers.boundedElastic()) runs the blocking operation on a separate thread pool, avoiding blocking the main event loop.

6. How would you test a controller using WebTestClient?

WebTestClient is a non-blocking, reactive client for testing WebFlux applications, simulating HTTP requests and verifying responses.

Example:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;

@WebFluxTest
public class MyControllerTest {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    public void testGetEndpoint() {
        webTestClient.get().uri("/my-endpoint")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Expected Response");
    }
}

WebTestClient sends a GET request to /my-endpoint, verifying the status and response body.

7. Explain how to create a custom operator.

Custom operators in WebFlux allow developers to define their own reactive transformations and operations, useful for specific business logic or performance optimizations.

Example:

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Operators;
import java.util.function.Function;

public class CustomOperatorExample {

    public static void main(String[] args) {
        Flux<Integer> flux = Flux.just(1, 2, 3, 4, 5)
                .transform(applyCustomOperator());

        flux.subscribe(System.out::println);
    }

    private static Function<Flux<Integer>, Flux<Integer>> applyCustomOperator() {
        return flux -> flux.map(i -> i * 2);
    }
}

The applyCustomOperator method defines a custom operator that doubles each element in the stream, applied using the transform method.

8. How would you implement an endpoint that streams server-sent events (SSE)?

Server-Sent Events (SSE) enable a server to push real-time updates to the client over a single HTTP connection. In WebFlux, you can implement an SSE endpoint using the Flux class.

Example:

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.time.LocalTime;

@RestController
public class SSEController {

    @GetMapping(value = "/stream-sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamEvents() {
        return Flux.interval(Duration.ofSeconds(1))
                   .map(sequence -> "SSE - " + LocalTime.now().toString());
    }
}

The streamEvents method returns a Flux emitting a new event every second, with the endpoint producing text/event-stream media type.

9. How does WebFlux support reactive programming principles?

WebFlux supports reactive programming principles by leveraging Project Reactor, which provides Mono and Flux for non-blocking operations and backpressure. It uses a non-blocking, event-driven model to handle requests and responses, processing many concurrent requests without being constrained by thread count.

Example:

@GetMapping("/hello")
public Mono<String> sayHello() {
    return Mono.just("Hello, World!");
}

The sayHello method returns a Mono emitting “Hello, World!”, demonstrating non-blocking asynchronous operations.

10. Describe the role of Context in Project Reactor and how it can be used.

In Project Reactor, Context is a key-value store associated with a reactive sequence, allowing the passage of contextual information downstream without modifying data flow. It is immutable, ensuring thread safety and consistency.

Example:

import reactor.core.publisher.Mono;
import reactor.util.context.Context;

public class ContextExample {
    public static void main(String[] args) {
        Mono<String> mono = Mono.just("Hello")
            .flatMap(value -> Mono.deferContextual(ctx -> {
                String user = ctx.get("user");
                return Mono.just(value + ", " + user);
            }))
            .contextWrite(Context.of("user", "John"));

        mono.subscribe(System.out::println); // Output: Hello, John
    }
}

A Mono is created with a string value, and flatMap accesses the Context to retrieve the “user” value. The contextWrite method adds the key-value pair to the Context.

Previous

10 String Manipulation Python Interview Questions and Answers

Back to Interview
Next

30 ReactJS Interview Questions and Answers