Content Negotiation and HttpMessageConverters in Spring Boot 3
Introduction
A modern API often needs to return different response formats depending on client needs (JSON, XML, sometimes custom media types). In this chapter, you will learn how Spring Boot performs content negotiation, how HttpMessageConverter works, and how to extend converters safely when default behavior is not enough.
Prerequisites
- Completed:
06_spring_mvc_basics_annotations_and_routing.md08_file_upload_download_and_web_extensions.md
- Basic understanding of request headers and controller return values
What Is Content Negotiation?
Content negotiation is the process where the server selects a response representation based on request context.
Typical signals:
Acceptheader (recommended standard)- URL parameter strategy (optional)
producesconstraints on endpoint mapping
Example:
GET /api/users/1
Accept: application/jsonvs
GET /api/users/1
Accept: application/xmlSame endpoint, different response formats.
Default Behavior in Spring Boot
With spring-boot-starter-web:
- JSON is enabled by default (Jackson)
- Spring picks a converter that supports:
- method return type
- selected media type
In most APIs, JSON is enough. But negotiation matters when you support multiple clients or backward-compatible integrations.
Force Output Type with produces
You can constrain endpoint output:
If client Accept does not match produces, Spring may return 406 Not Acceptable.
Add XML Response Support
By default, XML may not be enabled unless proper converter dependency is present.
Add dependency:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>DTO example:
Controller:
Test with:
curl -H "Accept: application/xml" http://localhost:8080/api/users/1Configure Parameter-Based Negotiation (Optional)
Header-based negotiation is standard, but Spring also supports query-parameter based negotiation.
application.yml example:
spring:
mvc:
contentnegotiation:
favor-parameter: true
parameter-name: format
media-types:
json: application/json
xml: application/xmlThen:
/api/users/1?format=json/api/users/1?format=xml
Warning
Parameter-based negotiation is convenient for demos, but Accept header is more REST-standard and usually preferred for production APIs.
How HttpMessageConverter Works
HttpMessageConverter converts:
- request body -> Java object
- Java object -> response body
Examples of built-in converters:
MappingJackson2HttpMessageConverter(JSON)StringHttpMessageConverter(text/plain)ByteArrayHttpMessageConverter(binary)- XML converter (if XML dependency is present)
Selection depends on:
- Java type
- media type
- converter capability (
canRead/canWrite)
Register Custom Converter
Suppose you want to support YAML output.
Add dependency:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>Custom converter:
Register converter:
Now clients can request:
Accept: text/yamlCommon Negotiation Errors
406 Not Acceptable
Reason:
- Requested media type unsupported
- Endpoint
producesdoes not matchAccept
Fix:
- add converter/dependency
- adjust
produces - send supported
Accept
415 Unsupported Media Type
Reason:
- Request body media type unsupported
- Missing
Content-Typefor request body
Fix:
- send
Content-Type: application/json(or correct type) - ensure converter can read that type
Unexpected converter chosen
Reason:
- converter order issues
- broad media type support in custom converter
Fix:
- narrow custom media types
- review converter registration order
Best Practices
- Prefer JSON as primary public API format unless integration requires others
- Use
Acceptheader as default negotiation mechanism - Keep custom converters focused and explicit in supported media types
- Avoid overloading one endpoint with too many formats unless truly needed
- Add integration tests per media type to prevent regression
Quick Recap
In this chapter, you learned:
- How Spring Boot decides response format
- How to use
producesandAccept - How to add XML/YAML capabilities
- How
HttpMessageConverterparticipates in request/response conversion - How to troubleshoot 406/415 media-type errors
Next chapter moves into data-access foundations, starting with JDBC data source configuration and connection pool basics.
FAQ
Should every API support XML?
No. JSON-only APIs are common. Add XML only when required by client contracts or legacy integrations.
Is query-parameter negotiation a bad practice?
Not always, but header-based negotiation is more standard and clearer for HTTP semantics.
Can custom converter break default JSON behavior?
Yes, if configured too broadly. Keep custom converter media types specific and test default JSON routes.
What is the difference between consumes and produces?
consumes: what request body content type endpoint acceptsproduces: what response content type endpoint emits
Do I need custom converters for most projects?
Usually no. Default converters cover common JSON/text/binary needs very well.