415 Unsupported MediaType for POST request in spring application

50,585

Solution 1

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

Solution 2

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

Solution 3

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\" }" 
Share:
50,585
brain storm
Author by

brain storm

Updated on July 22, 2022

Comments

  • brain storm
    brain storm almost 2 years

    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>
    
  • brain storm
    brain storm almost 8 years
    no it is not. I added accept header and it did not work either
  • Tahir Hussain Mir
    Tahir Hussain Mir almost 8 years
    Hey ! i updated my answer, i believe this is the issue. Please check sloution 2 @brainstorm
  • Hema
    Hema about 7 years
    @TahirHussainMir, hey i have added@ModelAttribute annotation.Control is hitting to the method but my object data is displaying null...?? any suggestion
  • Tahir Hussain Mir
    Tahir Hussain Mir about 7 years
    check the names of variables of object and the name fields in the html. They should be same. Like if there is variable String myName; then in html, the input field should have attribute name="myName"