skip to content

How do you add, remove, reorder, or reconfigure HttpMessageConverters? Contrast configureMessageConverters with extendMessageConverters.

level: seniorimportance: should knowfreq 45%

answer

  1. configure = REPLACE (non-empty skips defaults)
  2. extend = MODIFY after defaults (safe)
  3. add(0, ...) to win ordering
  4. prefer customizing ObjectMapper, not new converter
  5. Boot: declare converter bean; avoid @EnableWebMvc unless intentional

basics

~20 s

Implement WebMvcConfigurer. Override extendMessageConverters(list) to tweak the existing defaults (add, remove, reorder) while keeping them. Override configureMessageConverters(list) only if you want to fully REPLACE the defaults — if that list is non-empty, Spring adds no defaults.

solid answer

~40 s

Both are WebMvcConfigurer hooks. configureMessageConverters(List) lets you supply your own converter list; if you add anything, Spring treats it as authoritative and skips registering all defaults — so you lose byte[]/String/form/Jackson unless you re-add them. extendMessageConverters(List) is called AFTER the defaults are in place and is the safe hook for surgical changes: reorder, remove, or add one converter without discarding the rest. To just reconfigure Jackson, prefer customizing the ObjectMapper — in Boot via Jackson2ObjectMapperBuilder / a Jackson2ObjectMapperBuilderCustomizer, or by replacing the MappingJackson2HttpMessageConverter's mapper inside extendMessageConverters. Avoid rebuilding the whole list unless you truly intend to replace defaults. In Spring Boot you can also just declare an HttpMessageConverter bean and Boot will add it via HttpMessageConverters.

code

java · 24 lines
java
@Configuration
class WebConfig implements WebMvcConfigurer {

    // SAFE: keep all defaults, just tweak them.
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // Reconfigure the existing Jackson converter's ObjectMapper.
        for (HttpMessageConverter<?> c : converters) {
            if (c instanceof MappingJackson2HttpMessageConverter jackson) {
                jackson.getObjectMapper()
                       .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
            }
        }
        // Add a custom converter at highest precedence.
        converters.add(0, new ProtobufHttpMessageConverter());
    }

    // DANGER (shown for contrast): this REPLACES all defaults.
    // Adding only one converter here means no JSON/String/byte[] support.
    // @Override
    // public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    //     converters.add(new MappingJackson2HttpMessageConverter()); // defaults now skipped!
    // }
}

go deeper

for a junior

Know you customize converters via WebMvcConfigurer.

for a middle

State that extendMessageConverters preserves defaults and configureMessageConverters can replace them.

for a senior

Explain the empty-vs-non-empty behavior of configureMessageConverters and prefer ObjectMapper customization for Jackson tweaks.

for a principal

Discuss Boot's HttpMessageConverters bean collection, the @EnableWebMvc trade-off, and ordering-based precedence when inserting converters.

## The two WebMvcConfigurer hooks ```java public interface WebMvcConfigurer { default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {} default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {} } ``` ### configureMessageConverters — REPLACE `WebMvcConfigurationSupport` calls this first. **If the list is left empty**, Spring populates it with the full default set. **If you add even one converter**, Spring considers the list authoritative and **does not add any defaults**. Result: overriding this and adding only your custom converter silently drops JSON/String/byte[]/form support. Use it only when you deliberately want a hand-picked list. ### extendMessageConverters — MODIFY Called **after** the defaults have been added (whether the defaults or a configure-provided list). The `converters` list already contains the working set, so you can: - **add**: `converters.add(new MyConverter());` - **insert at a position** (to win ordering): `converters.add(0, new MyConverter());` - **remove**: `converters.removeIf(c -> c instanceof SomeConverter);` - **reconfigure**: find the existing `MappingJackson2HttpMessageConverter` and set a custom `ObjectMapper` or add supported media types. This is the recommended hook for almost all real needs because it preserves the defaults. ## Reconfiguring Jackson specifically Usually you don't want a new converter — you want Jackson to behave differently (date format, `FAIL_ON_UNKNOWN_PROPERTIES`, naming strategy, a `@JsonView`). Options, best-first: 1. **Customize the ObjectMapper** — in Spring Boot register a `Jackson2ObjectMapperBuilderCustomizer` bean, or set `spring.jackson.*` properties; both flow into the auto-configured mapper used by the converter. 2. **Replace the mapper on the converter** inside `extendMessageConverters` by locating the existing `MappingJackson2HttpMessageConverter`. 3. **Provide your own converter bean** — in Boot, any `HttpMessageConverter` bean is collected by `HttpMessageConverters` and added to the list (defaults preserved). ## Spring Boot nuance Boot's `WebMvcAutoConfiguration` respects `WebMvcConfigurer` hooks AND auto-adds converter beans. Boot generally advises **not** to override `configureMessageConverters` (you'd lose Boot's carefully-built defaults, including the Boot-configured Jackson mapper). Prefer a converter bean or `extendMessageConverters`. Note: adding a full `@EnableWebMvc` in a Boot app disables the MVC auto-config, which changes this picture — then you own the defaults. ## Common mistakes - Overriding `configureMessageConverters`, adding a single custom converter, then wondering why JSON stopped working (defaults were dropped). - Adding a second `MappingJackson2HttpMessageConverter` with a different mapper but placing it after the original, so the original still wins for `application/json`. - Mutating a shared static `ObjectMapper` from the converter (thread-safety is fine for read/write, but mutating configuration at runtime is not).

  • You override configureMessageConverters and add one Jackson converter — why do plain-text and byte[] endpoints break?
    Because a non-empty configureMessageConverters list is treated as the complete set, so Spring skips registering all defaults (StringHttpMessageConverter, ByteArrayHttpMessageConverter, etc.). Use extendMessageConverters, or re-add every default explicitly.
  • In Spring Boot, what's the least invasive way to change how dates are serialized in JSON responses?
    Configure the ObjectMapper, not the converter: set spring.jackson.date-format / write-dates-as-timestamps properties, or register a Jackson2ObjectMapperBuilderCustomizer bean. Boot feeds that mapper into the existing MappingJackson2HttpMessageConverter.

saying these in an interview costs you the question

  • Believing configureMessageConverters merely appends to the defaults.
  • Thinking you must write a new converter to change Jackson settings (customize the ObjectMapper instead).
  • Adding a converter at the end of the list and expecting it to override an earlier one for the same media type.

context