skip to content

Filters, Codecs, Errors & Streaming

The surrounding reactive machinery: WebFilters, exception handling, codecs, SSE and streaming responses, configuration hooks, and WebSockets. Interviewers dip in when they want to know how far past hello-world your WebFlux experience goes.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

explore

questions

page 1 of 2

In Spring WebFlux, what are Encoder/Decoder and HttpMessageReader/HttpMessageWriter, and what do they do?

level: juniorimportance: must knowfreq 55%

answer

  1. Encoder=objects->bytes, Decoder=bytes->objects
  2. Reader/Writer add HTTP concerns
  3. EncoderHttpMessageWriter wraps Encoder
  4. Everything is Flux<DataBuffer>
  5. Jackson2JsonEncoder/Decoder = JSON pair

basics

~10 s

They convert between Java objects and the raw bytes of an HTTP body. A Decoder/HttpMessageReader turns request bytes into objects; an Encoder/HttpMessageWriter turns response objects back into bytes (e.g. JSON).

solid answer

~40 s

WebFlux replaces MVC's HttpMessageConverter with two reactive abstractions. Encoder<T> serializes a stream of objects into bytes; Decoder<T> deserializes bytes into objects. These are content-only, unaware of HTTP. HttpMessageWriter and HttpMessageReader wrap them and add HTTP concerns like Content-Type negotiation and headers. The standard adapters are EncoderHttpMessageWriter and DecoderHttpMessageReader, so registering a codec usually means registering an Encoder/Decoder pair. Everything works on Reactive Streams Publishers (Flux/Mono) of DataBuffer rather than blocking byte arrays, so bodies can be processed as they stream in and out. Jackson2JsonEncoder/Jackson2JsonDecoder are the built-in JSON pair; there are also codecs for plain strings, form data, multipart, and byte buffers.

code

java · 19 lines
java
// Content-only layer
public interface Encoder<T> {
    Flux<DataBuffer> encode(Publisher<? extends T> inputStream,
                            DataBufferFactory bufferFactory,
                            ResolvableType elementType,
                            MimeType mimeType,
                            Map<String, Object> hints);
}

public interface Decoder<T> {
    Flux<T> decode(Publisher<DataBuffer> inputStream,
                   ResolvableType elementType,
                   MimeType mimeType,
                   Map<String, Object> hints);
}

// HTTP-aware wrappers used at runtime:
//   EncoderHttpMessageWriter  wraps an Encoder<T>
//   DecoderHttpMessageReader  wraps a Decoder<T>

go deeper

for a junior

Know the direction: Decoder/Reader = incoming bytes to objects, Encoder/Writer = objects to outgoing bytes, and that JSON uses Jackson.

for a middle

Explain the two layers (content Encoder/Decoder vs HTTP Reader/Writer) and that they stream DataBuffers reactively.

for a senior

Contrast with MVC's HttpMessageConverter and explain MIME/type-based selection plus the EncoderHttpMessageWriter/DecoderHttpMessageReader wrapping.

for a principal

Discuss streaming vs aggregation semantics, reference-counted DataBuffer lifecycle, and how codec selection interacts with content negotiation across server and WebClient.

## The problem they solve An HTTP body on the wire is just bytes. A controller wants to work with Java objects (a `User`, a `List<Order>`). Something must translate between the two. In blocking **Spring MVC** that job belongs to `HttpMessageConverter`. In reactive **Spring WebFlux** the same job is split across a small layered set of interfaces designed to work with streaming, non-blocking data. ## The two layers **1. Content codecs (HTTP-agnostic):** - `Encoder<T>` — takes a `Publisher<? extends T>` (a stream of objects) and produces a `Flux<DataBuffer>` (a stream of byte chunks). Used to write responses / request bodies. - `Decoder<T>` — takes a `Publisher<DataBuffer>` and produces a `Flux<T>` (objects). Used to read request / response bodies. These know nothing about HTTP headers or status codes — only how to turn objects into bytes and back for a given `MimeType`. **2. Message codecs (HTTP-aware):** - `HttpMessageWriter<T>` — writes a `Publisher<T>` to a `ReactiveHttpOutputMessage`, choosing the `Content-Type`, setting `Content-Length`, etc. - `HttpMessageReader<T>` — reads a `ReactiveHttpInputMessage` into a `Flux<T>` / `Mono<T>`, checking the request's `Content-Type`. The glue: `EncoderHttpMessageWriter` wraps an `Encoder`, and `DecoderHttpMessageReader` wraps a `Decoder`. So most of the time you supply an `Encoder`/`Decoder` and Spring wraps it into the HTTP-aware layer automatically. ## DataBuffer `DataBuffer` is Spring's abstraction over a chunk of bytes (it wraps a Netty `ByteBuf` or a `java.nio.ByteBuffer` depending on the runtime). Because bodies are streams of `DataBuffer`, WebFlux can process data incrementally without buffering the whole payload into a `byte[]` — the key difference from MVC. ## Built-in codecs - **JSON:** `Jackson2JsonEncoder` / `Jackson2JsonDecoder` (Jackson-backed). - **Strings:** `CharSequenceEncoder` / `StringDecoder`. - **Bytes / resources:** `ByteArrayEncoder`, `ByteBufferEncoder`, `DataBufferEncoder`, `ResourceEncoder`/`ResourceDecoder`. - **Form & multipart:** `FormHttpMessageReader`/`Writer`, multipart readers. - (Optional) protobuf, Jackson Smile, XML (JAXB/Jackson) codecs. ## Where they live On the server the active set is held by a `ServerCodecConfigurer`; on the client (`WebClient`) by a `ClientCodecConfigurer`. You customize them via `WebFluxConfigurer.configureHttpMessageCodecs(...)` or `WebClient.Builder.codecs(...)`. ## Gotchas - Codecs are selected by **MIME type** and target **type** — if none matches you get `415 Unsupported Media Type` (read) or `406 Not Acceptable` / no writer found. - With streaming JSON of multiple elements, WebFlux uses **NDJSON / `application/stream+json`** semantics for true streaming; a plain `application/json` array is aggregated. - Because Netty `DataBuffer`s are reference-counted, low-level custom decoders must **release** buffers (`DataBufferUtils.release`) to avoid leaks — the built-in codecs handle this for you.

  • What is the equivalent abstraction in Spring MVC, and why can't WebFlux reuse it?
    Spring MVC uses HttpMessageConverter, which reads/writes the whole body from blocking InputStream/OutputStream (byte[]). WebFlux is non-blocking and stream-based, so it needs codecs that operate on Publisher<DataBuffer> instead.
  • How does WebFlux decide which codec to use for a given request or response?
    By matching the message's Content-Type (or the request's Accept header for writing) against each codec's supported MimeTypes, plus checking the target Java type it can handle. First matching reader/writer wins; no match yields 415 or 406.

saying these in an interview costs you the question

  • Saying WebFlux uses HttpMessageConverter like MVC
  • Claiming Encoder/Decoder handle HTTP headers/status (that's the Reader/Writer layer)
  • Thinking bodies are always buffered into a byte[] before decoding

context

open as a page

How do you handle an exception thrown by a WebFlux controller method, both locally and globally?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Add a method annotated with @ExceptionHandler in the same controller to handle it locally. To handle exceptions from many controllers in one place, put @ExceptionHandler methods in a class annotated with @ControllerAdvice (or @RestControllerAdvice).

open as a page

How do you expose a streaming endpoint in Spring WebFlux, and what does returning a Flux with produces=MediaType.TEXT_EVENT_STREAM_VALUE actually do?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Return a Flux from the controller and set produces=MediaType.TEXT_EVENT_STREAM_VALUE ("text/event-stream"). Spring keeps the HTTP response open and writes each emitted item to the client as a Server-Sent Event, instead of buffering one JSON array.

open as a page

What is a Spring WebFlux `WebFilter`, and how does it relate to the servlet `Filter`?

level: juniorimportance: must knowfreq 68%

basics

~10 s

WebFilter is WebFlux's reactive interface for intercepting every request/response, the non-blocking equivalent of a servlet Filter. Its filter(exchange, chain) method returns Mono<Void>, and you call chain.filter(exchange) to continue to the next filter or handler.

open as a page

What is WebFluxConfigurer and how do you use it to customize Spring WebFlux?

level: juniorimportance: must knowfreq 55%

basics

~10 s

WebFluxConfigurer is an interface with optional callback methods. You implement it on a @Configuration class to customize the reactive web setup — CORS, formatters, argument resolvers, codecs, content negotiation — without replacing Spring's defaults.

open as a page

In Spring WebFlux, what is the WebSocketHandler interface and what does its handle(WebSocketSession) method return, and why?

level: juniorimportance: must knowfreq 62%

basics

~10 s

WebSocketHandler is the reactive interface you implement to handle a WebSocket connection. Its single method handle(WebSocketSession) returns Mono<Void>, a reactive signal that completes when your handling of the session is done (which closes it).

open as a page

What is CodecConfigurer's maxInMemorySize, why does it exist, and how do you change it?

level: middleimportance: must knowfreq 60%

basics

~20 s

It's a limit on how many bytes a codec will buffer in memory when it must read the whole body before parsing. Default is 256 KB. Exceeding it throws DataBufferLimitException. You raise it via CodecConfigurer.defaultCodecs().maxInMemorySize(...).

open as a page

Inside a `WebFilter`, how do you continue the chain versus short-circuit and return a response immediately (e.g. reject a request)?

level: middleimportance: must knowfreq 60%

basics

~10 s

To continue, return chain.filter(exchange). To short-circuit, do NOT call the chain: set the response status/headers on exchange.getResponse() and return exchange.getResponse().setComplete() (a Mono<Void> that finishes the exchange), so no downstream filter or handler runs.

open as a page

What does @EnableWebFlux do, and what is its critical interaction with Spring Boot auto-configuration?

level: middleimportance: must knowfreq 60%

basics

~20 s

@EnableWebFlux bootstraps Spring's reactive web infrastructure by importing DelegatingWebFluxConfiguration. In Spring Boot it also turns OFF Boot's WebFlux auto-configuration, so you take full manual control. In plain Spring you need it to enable WebFlux at all.

open as a page

How do WebSocketSession.receive() and WebSocketSession.send() work with Flux<WebSocketMessage>, and how do you wire them together in a handler?

level: middleimportance: must knowfreq 55%

basics

~20 s

session.receive() returns a Flux<WebSocketMessage> of inbound frames; session.send(Publisher<WebSocketMessage>) takes an outbound stream and returns Mono<Void>. You transform the inbound Flux (or a separate source) into outbound WebSocketMessages and pass it to send(), returning that Mono.

open as a page

For an infinite Flux served as SSE, how does Spring WebFlux flush items incrementally, and how does backpressure prevent a fast producer from overwhelming a slow client?

level: seniorimportance: must knowfreq 40%

basics

~20 s

The reactive stack writes and flushes each emitted item as bytes become sendable, keeping the connection open. Backpressure flows from the TCP write buffer up through Reactor: the encoder only requests the next item when the socket can accept more, so a slow client naturally slows the producer.

open as a page

How do you expose a reactive WebSocketHandler at a URL in Spring WebFlux — what beans (SimpleUrlHandlerMapping, WebSocketHandlerAdapter, HandshakeWebSocketService) are involved and what does each do?

level: seniorimportance: must knowfreq 50%

basics

~20 s

Register a SimpleUrlHandlerMapping bean that maps URL paths to your WebSocketHandler instances (with a high order so it wins over annotated controllers), plus a WebSocketHandlerAdapter bean. The adapter uses a WebSocketService — by default HandshakeWebSocketService — to perform the HTTP-to-WebSocket upgrade handshake.

open as a page

How does Spring WebFlux serialize and deserialize JSON, and what role does Jackson2JsonEncoder/Decoder play?

level: middleimportance: should knowfreq 45%

basics

~10 s

WebFlux uses Jackson under the hood. Jackson2JsonEncoder turns your objects into JSON bytes for the response; Jackson2JsonDecoder turns request JSON bytes back into objects. They use a Jackson ObjectMapper, like MVC does.

open as a page

What is the ErrorAttributes abstraction in reactive Spring, and how does DefaultErrorAttributes participate in the error response?

level: middleimportance: should knowfreq 45%

basics

~20 s

ErrorAttributes is an interface that produces the map of fields (status, error, message, path, timestamp...) used to build the error response body. DefaultErrorAttributes is Boot's implementation; it also stores the exception so the error handler can read it. Extend it to customize the fields.

open as a page

What is the WebExceptionHandler interface and how does the global exception-handling chain work in WebFlux?

level: middleimportance: should knowfreq 55%

basics

~20 s

WebExceptionHandler is a functional interface with one method: Mono<Void> handle(ServerWebExchange exchange, Throwable ex). Beans of this type form an ordered chain that catches exceptions not handled inside controllers. The first one to complete the exchange wins.

open as a page

When and why would you return Flux<ServerSentEvent<T>> instead of a plain Flux<T> for an SSE endpoint?

level: middleimportance: should knowfreq 55%

basics

~20 s

Use Flux<ServerSentEvent<T>> when you need to set SSE metadata: the event name, an id (so clients can resume after reconnecting), the retry/reconnect delay, or comment lines. A plain Flux<T> only gives you the data field.

open as a page

How do you control the execution order of multiple `WebFilter`s, and what does the order value mean?

level: middleimportance: should knowfreq 52%

basics

~20 s

Give each filter an order via the @Order annotation or by implementing Ordered. Spring sorts WebFilter beans by that value — lower value = higher precedence = runs earlier (and, because filters wrap each other, later on the way back out).

open as a page

How do you configure global CORS in Spring WebFlux via WebFluxConfigurer?

level: middleimportance: should knowfreq 50%

basics

~10 s

Override addCorsMappings(CorsRegistry) in a WebFluxConfigurer bean. Use registry.addMapping(pathPattern) and chain allowedOrigins, allowedMethods, allowedHeaders, allowCredentials, and maxAge to define which cross-origin requests are permitted.

open as a page

Why does WebFlux use DataBuffer-based codecs instead of MVC's HttpMessageConverter, and what are the practical consequences?

level: seniorimportance: should knowfreq 38%

basics

~10 s

HttpMessageConverter is blocking — it reads/writes the whole body via InputStream/OutputStream. WebFlux is non-blocking, so it uses Encoder/Decoder over reactive streams of DataBuffer, letting it process bodies in chunks without tying up a thread.

open as a page

What does Spring Boot's DefaultErrorWebExceptionHandler do, and how would you customize the error response it produces?

level: seniorimportance: should knowfreq 50%

basics

~20 s

It is Spring Boot's global fallback error handler for WebFlux. It renders a JSON (or Whitelabel HTML) error response for any unhandled exception, using ErrorAttributes for the body. Customize it by supplying your own ErrorAttributes or by subclassing AbstractErrorWebExceptionHandler.

open as a page

Compare application/x-ndjson streaming with text/event-stream (SSE) in WebFlux. When would you choose each?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Both stream a Flux incrementally. NDJSON (application/x-ndjson) sends each item as one JSON object per line — a plain data stream, easy for API/service-to-service clients. SSE (text/event-stream) adds event names, ids, retry, and browser EventSource support.

open as a page

How do you modify the request or response from a `WebFilter` given that `ServerWebExchange` is immutable? Explain `exchange.mutate()`.

level: seniorimportance: should knowfreq 46%

basics

~20 s

ServerWebExchange (and its request/response) are effectively immutable, so you can't set fields directly. Call exchange.mutate() to get a builder, apply changes (e.g. .request(r -> r.header(...))), call .build() to get a new exchange, and pass THAT to chain.filter(...).

open as a page

Explain configureHttpMessageCodecs, addFormatters, and addArgumentResolvers in WebFluxConfigurer — what each customizes and how they differ.

level: seniorimportance: should knowfreq 45%

basics

~10 s

configureHttpMessageCodecs tunes body serialization/deserialization (via ServerCodecConfigurer). addFormatters registers Converter/Formatter for turning strings into types (path vars, params). addArgumentResolvers adds custom HandlerMethodArgumentResolvers for controller parameters the framework doesn't handle natively.

open as a page

How does content negotiation work in Spring WebFlux, and how do you customize it via WebFluxConfigurer?

level: seniorimportance: should knowfreq 40%

basics

~20 s

WebFlux picks the response media type using a RequestedContentTypeResolver, which by default reads the Accept header. You customize it by overriding configureContentTypeResolver(RequestedContentTypeResolverBuilder) — e.g. enable a query parameter strategy or set a default media type.

open as a page

In a reactive WebSocketHandler, what exactly controls when the session closes, and how do close, errors, and cleanup propagate through the returned Mono<Void>?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The session stays open while the Mono<Void> you return is unterminated. When that Mono completes, the framework closes the session normally; when it errors, the session closes with an error status. The client disconnecting completes receive(), which typically completes your Mono.

open as a page

Across @ExceptionHandler, WebExceptionHandler, and Boot's error handler, how do you decide which layer owns error handling — and in what order do they see an exception?

level: principalimportance: should knowfreq 35%

basics

~20 s

A controller error is offered first to @ExceptionHandler (local then @ControllerAdvice). If unhandled — or if it came from a filter/functional endpoint — it propagates to the ordered WebExceptionHandler chain, ending in Boot's DefaultErrorWebExceptionHandler (order -1) which renders from ErrorAttributes.

open as a page

What production concerns arise when running long-lived SSE endpoints at scale in Spring WebFlux, and how do you address them?

level: principalimportance: should knowfreq 30%

basics

~20 s

Long-lived connections tie up sockets and cross proxies/load balancers that may buffer or time out idle streams. Address with heartbeats, sensible timeouts, disconnect cleanup (doOnCancel), non-blocking pipelines, resumption via Last-Event-ID, and disabling proxy response buffering.

open as a page

You need a `WebFilter` that measures total request latency and propagates a correlation ID to downstream reactive/logging code. What are the threading and context-propagation pitfalls, and how do you do it correctly?

level: principalimportance: should knowfreq 33%

basics

~20 s

Never use a ThreadLocal/MDC set imperatively — reactive work hops threads, so the value won't be there downstream. Measure latency by timing around the returned Mono (record start, then .doFinally on chain.filter). Propagate the correlation ID via the Reactor Context using .contextWrite(...), not a thread-local.

open as a page

What concurrency, backpressure, and buffer-management pitfalls must you handle when broadcasting to many reactive WebSocket sessions, and how do you address them?

level: principalimportance: should knowfreq 28%

basics

~20 s

A session supports a single ordered write stream, so never call send() concurrently or write from multiple threads. For broadcast, use a shared Sinks.many() and let each session subscribe with its own send(), applying backpressure strategy (buffer/drop) per slow client, and mind pooled DataBuffer retain/release when reusing payloads.

open as a page

How do you register a custom Encoder/Decoder or tune the codec set via CodecConfigurer, and how do default vs custom codecs interact?

level: principalimportance: nice to knowfreq 25%

basics

~10 s

Implement Encoder/Decoder (or HttpMessageReader/Writer), then register it in CodecConfigurer via customCodecs().register(...). Use defaultCodecs() to tweak built-ins (like maxInMemorySize or the Jackson mapper). Do this in WebFluxConfigurer.configureHttpMessageCodecs on the server or WebClient.Builder.codecs.

open as a page

showing 1–30 of 31