What is the difference between configureMessageConverters and extendMessageConverters?
answer
- configure = replace (add one → defaults dropped)
- extend = runs after defaults, add/reorder safely
- order decides which converter wins
- Boot: prefer ObjectMapper / Jackson2ObjectMapperBuilderCustomizer
- classic bug: overrode configure, lost String/byte converters
basics
~20 sconfigureMessageConverters lets you supply the whole converter list — if you add any, the framework defaults are NOT added. extendMessageConverters runs after defaults are in place, so you keep them and just add or reorder converters. Prefer extend to keep defaults.
solid answer
~40 sBoth callbacks deal with HttpMessageConverters — the components that (de)serialize @RequestBody/@ResponseBody payloads (JSON via Jackson, String, byte[], etc.). configureMessageConverters(List) is your chance to REPLACE the default list: if you add even one converter, Spring registers only what you added and skips its defaults, so you're fully responsible. If you leave it empty, defaults are used. extendMessageConverters(List) is invoked AFTER the default converters have been populated, so it's the safe hook to add a converter, remove one, or reorder (e.g. move your custom converter ahead of Jackson) without losing the built-ins. In Spring Boot, the usual need — customize Jackson — is better done via a Jackson2ObjectMapperBuilderCustomizer or ObjectMapper bean; you rarely touch these callbacks. When you do, extendMessageConverters is almost always the right one.
code
java · 16 lines@Configuration
public class ConverterConfig implements WebMvcConfigurer {
// SAFE: keep all defaults, just put our converter first
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MyCsvHttpMessageConverter());
}
// DANGER: adding here means the framework's default converters
// (String, byte[], Jackson JSON...) are NOT registered.
// @Override
// public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// converters.add(new MappingJackson2HttpMessageConverter());
// }
}go deeper
May not know these callbacks; fine to recognize converters handle @RequestBody/@ResponseBody.
Should know extend keeps defaults, configure can replace them.
Should articulate the add-one-drops-all gotcha, ordering semantics, and the Boot ObjectMapper alternative.
Should set team conventions (prefer ObjectMapper/customizer; reserve extend for genuinely new converter types) and reason about media-type/ordering conflicts.
## Background: what an HttpMessageConverter is An `HttpMessageConverter<T>` reads an HTTP request body into a Java object (for `@RequestBody`) and writes a Java object to the response body (for `@ResponseBody`/`ResponseEntity`), choosing based on `Content-Type`/`Accept`. Defaults include `MappingJackson2HttpMessageConverter` (JSON), `StringHttpMessageConverter`, `ByteArrayHttpMessageConverter`, form converters, and (if on classpath) XML/Jackson-XML. ## `configureMessageConverters(List<HttpMessageConverter<?>>)` Called to let you **define the converter list**. Contract: **if the list you receive ends up non-empty because you added converters, the framework's default converters are NOT registered** — you have taken ownership. If you add nothing, the defaults are registered normally. Use only when you truly want full control over the exact set and order of converters. ## `extendMessageConverters(List<HttpMessageConverter<?>>)` Called **after** the converter list has already been populated (either by defaults or by whatever `configureMessageConverters` produced). This is the hook to **modify** the assembled list: add a converter, remove one, or change ordering. Ordering matters — the first converter that supports the target type/media type wins, so to make a custom JSON converter take precedence over the default Jackson one you insert it at index 0 here. ## Why the distinction matters (the classic gotcha) A very common bug: a developer overrides `configureMessageConverters`, adds a single custom converter, and then everything else (String, byte[], form, even standard JSON edge cases) stops working — because adding one converter **suppressed all defaults**. The fix is almost always to use `extendMessageConverters` instead, which preserves the defaults. ## Spring Boot angle In Boot, if the goal is to tune JSON, you usually don't touch either callback. Instead: - Define an `ObjectMapper` bean, or a `Jackson2ObjectMapperBuilderCustomizer`, or set `spring.jackson.*` properties. Boot's auto-configured `MappingJackson2HttpMessageConverter` picks up that `ObjectMapper` automatically. Reach for `extendMessageConverters` only when you need a genuinely additional converter type (e.g. a Protobuf or CSV converter) or need to reorder. ## Summary table - `configureMessageConverters`: define/replace the list; adding any converter drops defaults. - `extendMessageConverters`: runs after the list exists; add/remove/reorder while keeping defaults.
- You only need to change how dates are serialized in JSON. Which approach in Boot?Don't touch the converter callbacks. Configure Jackson: an ObjectMapper/Jackson2ObjectMapperBuilderCustomizer bean or spring.jackson.date-format/serialization properties. Boot's auto-configured Jackson converter uses that ObjectMapper.
- Why does converter order matter?For a given target type and requested media type, Spring picks the first converter in the list that supports it. To make a custom converter win over a default, insert it earlier (e.g. index 0 via extendMessageConverters).
saying these in an interview costs you the question
- Saying configureMessageConverters adds to the defaults (it replaces them)
- Believing order in the converter list is irrelevant
- Using configureMessageConverters to add one converter and expecting defaults to remain
- In Boot, hacking converters to change Jackson settings instead of configuring the ObjectMapper