Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

415 Unsupported MediaType for POST request in spring application

I have a very simple Spring Application (NOT spring boot). I have implemented a GET and POST controller methods. the GET method works fine. But the POST is throwing 415 Unsupported MediaType. Steps to reproduce are available below

ServiceController. java

package com.example.myApp.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;


    @Controller
    @RequestMapping("/service/example")
    public class ServiceController {

        @RequestMapping(value="sample", method = RequestMethod.GET)
        @ResponseBody
    public String getResp() {
        return "DONE";
    }

    @RequestMapping(value="sample2", method = RequestMethod.POST, consumes = "application/json")
    @ResponseBody
    public String getResponse2(@RequestBody Person person) {
        return "id is " + person.getId();
    }

}

class Person {

    private int id;
    private String name;

    public Person(){

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

AppConfig.java

package com.example.myApp.app.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan("com.example.myApp")
public class AppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/test/**").addResourceLocations("/test/").setCachePeriod(0);
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(0);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(0);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(0);
    }
}

AppInitializer.java

package com.example.myApp.app.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {


        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();

        rootContext.register(AppConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher =
                servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));

        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

    }


}

The code is available here:

git clone https://bitbucket.org/SpringDevSeattle/springrestcontroller.git
./gradlew clean build tomatrunwar

This spins up embedded tomcat.

Now you can curl the following

curl -X GET -H "Content-Type: application/json" "http://localhost:8095/myApp/service/example/sample"

works fine

But

curl -X POST -H "Content-Type: application/json" '{
    "id":1,
    "name":"sai"
}' "http://localhost:8095/myApp/service/example/sample2"

Throws 415 unsupported MediaType

<body>
        <h1>HTTP Status 415 - </h1>
        <HR size="1" noshade="noshade">
        <p>
            <b>type</b> Status report
        </p>
        <p>
            <b>message</b>
            <u></u>
        </p>
        <p>
            <b>description</b>
            <u>The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.</u>
        </p>
        <HR size="1" noshade="noshade">
        <h3>Apache Tomcat/7.0.54</h3>
    </body>
like image 845
brain storm Avatar asked Jun 28 '16 03:06

brain storm


People also ask

How do I fix unsupported media type 415?

Fixing 415 Unsupported Media Type errorsEnsure that you are sending the proper Content-Type header value. Verify that your server is able to process the value defined in the Content-Type header. Check the Accept header to verify what the server is actually willing to process.

What is the use of Mediatype in spring boot?

In Spring REST APIs, Spring uses 'application/json' as a default media type. That is why, a REST controller can consume or produce JSON format payloads without having to specify the media types explicitly. Thus, in order to consume or produce data in a different form, the controller needs to specify that explicitly.

What is a 415 error?

The HTTP 415 Unsupported Media Type client error response code indicates that the server refuses to accept the request because the payload format is in an unsupported format. The format problem might be due to the request's indicated Content-Type or Content-Encoding , or as a result of inspecting the data directly.


3 Answers

Accept Header might be the issue. As far as i remember, when you send a request via curl it adds a default header accept : */*
But in case of JSON you have to mention the accept header
as accept : application/json
similarly you have mentioned the content-Type.

And little more, i dont know what is that, but don't you think you have to place "request mappings" like that

@RequestMapping(value="/sample" ...
@RequestMapping(value="/sample2" ...

This may not be the case, but accept header is the thing, i think is the main issue.
Solution 2
Since you have this code

public String getResponse2(@RequestBody Person person)

I have already faced this problem before and the solution two may help here

FormHttpMessageConverter which is used for @RequestBody-annotated parameters when content type is application/x-www-form-urlencoded cannot bind target classes as @ModelAttribute can). Therefore you need @ModelAttribute instead of @RequestBody

Either Use @ModelAttribute annotation instead of @RequestBody like this

public String getResponse2(@ModelAttribute Person person)

I provided the same answer to somebody and it helped. here is that answer of mine

like image 187
Tahir Hussain Mir Avatar answered Oct 22 '22 04:10

Tahir Hussain Mir


I found the solution and I want to post here so it benefits others.

Firstly I need to include jackson in my classpath, which I added in build.gradle as follows:

 compile 'com.fasterxml.jackson.core:jackson-databind:2.7.5'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.5'
    compile 'com.fasterxml.jackson.core:jackson-core:2.7.5'

Next, I have to change my AppConfig which extends WebMvcConfigurerAdapter as follows:

@Configuration
@EnableWebMvc
@ComponentScan("com.example.myApp")
public class AppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/test/**").addResourceLocations("/test/").setCachePeriod(0);
        registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(0);
        registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(0);
        registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(0);
    }


    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        converters.add(new MappingJackson2HttpMessageConverter());
        super.configureMessageConverters(converters);
    }
}

That is all and everything worked nicely

like image 37
brain storm Avatar answered Oct 22 '22 04:10

brain storm


can you trying using the -d option in curl

curl -H "Content-Type: application/json" -X POST -d
 '{"id":"1,"name":"sai"}'
 http://localhost:8095/myApp/service/example/sample2

Also, if you use windows you should escape double quotes

-d "{ \"id\": 1, \"name\":\"sai\" }" 
like image 1
Periklis Douvitsas Avatar answered Oct 22 '22 04:10

Periklis Douvitsas