Resolving 415 Unsupported Media Type Errors for POST JSON Requests in Spring MVC

Nov 12, 2025 · Programming · 15 views · 7.8

Keywords: Spring MVC | JSON | 415 Error | Message Converter | Serialization Configuration

Abstract: This article provides an in-depth analysis of the common 415 Unsupported Media Type error when handling JSON POST requests in Spring MVC. Through a detailed case study of a jQuery AJAX POST request, it explores the root causes and multiple solutions. The primary focus is on removing JSON serialization/deserialization annotations and configuring custom ObjectMapper, supplemented with practical techniques like setting request headers and checking constructors. With code examples and architectural principles, it offers comprehensive guidance for problem diagnosis and resolution.

Problem Background and Phenomenon Analysis

In Spring MVC-based web application development, handling JSON format POST requests is a common requirement. However, developers frequently encounter HTTP 415 Unsupported Media Type errors, indicating that the server cannot process the media type sent by the client.

From the provided case, the developer uses jQuery to send a POST request to a Spring MVC controller:

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

The custom postJSON function configures the correct Content-Type:

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

The server-side controller uses the @RequestBody annotation to receive JSON data:

@RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

Despite correctly setting Content-Type: application/json in the request headers and having proper JSON data format, the request still returns a 415 error.

Core Problem Diagnosis

The root cause of the 415 error is that Spring's message converters cannot properly process the incoming JSON data. This typically involves the following aspects:

Message Converter Configuration Issues: Spring uses HttpMessageConverter to handle the conversion of request and response bodies. When no suitable converter can handle the application/json media type, a 415 error is thrown.

Serialization/Deserialization Conflicts: As mentioned in the best answer, when entity classes have annotations like @JSONSerialize and @JSONDeserialize, they may conflict with Spring's default Jackson configuration, leading to conversion failures.

Request Header Completeness: Although Content-Type is correctly set, the Accept header is equally important. The Accept header informs the server about the expected response format, and @ResponseBody relies on this header to determine how to serialize the response data.

Primary Solutions

Solution 1: Unified Serialization Configuration (Recommended)

Remove specific serialization annotations from entity classes and configure uniformly in a custom ObjectMapper:

@Configuration
public class CustomObjectMapper {
    
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        
        // Configure serializers
        SimpleModule module = new SimpleModule();
        module.addSerializer(ProductCategory.class, new ProductCategorySerializer());
        module.addDeserializer(ProductCategory.class, new ProductCategoryDeserializer());
        
        mapper.registerModule(module);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        
        return mapper;
    }
}

This approach ensures consistency in serialization and deserialization logic, avoiding annotation conflicts.

Solution 2: Complete Request Header Configuration

Set both Content-Type and Accept headers in the jQuery AJAX call:

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
        headers: { 
            'Accept': 'application/json',
            'Content-Type': 'application/json' 
        },
        'type': 'POST',
        'url': url,
        'data': JSON.stringify(data),
        'dataType': 'json',
        'success': callback
    });
};

The Content-Type header is used by @RequestBody to determine the format of the request data, while the Accept header is used by @ResponseBody to determine the format of the response data.

Additional Troubleshooting Points

Check Constructors: Ensure that the class annotated with @RequestBody has an accessible no-argument constructor. Spring needs to instantiate objects through reflection, and if a suitable constructor is missing, the conversion process will fail.

public class ProductCategory {
    private Long idProductCategory;
    private String description;
    
    // Must have a no-argument constructor
    public ProductCategory() {}
    
    // Getter and Setter methods
    public Long getIdProductCategory() { return idProductCategory; }
    public void setIdProductCategory(Long idProductCategory) { 
        this.idProductCategory = idProductCategory; 
    }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { 
        this.description = description; 
    }
}

Simplify Test Classes: When troubleshooting, create a simplified test class to verify basic functionality:

public class SimpleCategory {
    private String name;
    private String value;
    
    public SimpleCategory() {}
    
    // Simple getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public String getValue() { return value; }
    public void setValue(String value) { this.value = value; }
}

Architectural Design Considerations: As mentioned in the reference article, entity classes should not be directly used for data exchange in REST services. It is recommended to adopt a three-tier architecture, using DTOs (Data Transfer Objects) for data transfer between layers to avoid exposing internal implementation details.

In-Depth Principle Analysis

The process of Spring MVC handling @RequestBody involves multiple components:

Message Converter Chain: Spring maintains a list of HttpMessageConverters that attempt to convert the request body in sequence. When encountering application/json content type, MappingJackson2HttpMessageConverter is responsible for processing.

Type Matching: The converter checks whether the target type (ProductCategory) can be deserialized. This includes checking class accessibility, constructors, field mappings, etc.

Error Handling Mechanism: When all converters fail to process the request, Spring throws HttpMediaTypeNotSupportedException, which is eventually converted to a 415 status code.

Understanding these underlying mechanisms helps in more effectively diagnosing and resolving similar issues.

Best Practices Summary

Based on the analysis in this article and practical experience, the following best practices are recommended:

Unified Serialization Configuration: Avoid mixing serialization annotations from different frameworks on entity classes, and manage serialization logic uniformly in configuration classes.

Complete Request Header Settings: Set both Content-Type and Accept headers on the client side to ensure consistency in request and response formats.

Appropriate Architectural Layering: Use the DTO pattern to separate domain models from interface contracts, improving code maintainability and flexibility.

Step-by-Step Troubleshooting Strategy: When encountering a 415 error, follow the sequence of constructor check → request header verification → serialization configuration → architectural design review.

Through systematic analysis and proper configuration, 415 Unsupported Media Type errors in Spring MVC can be effectively resolved, ensuring smooth processing of JSON requests.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.