Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC: @ResponseBody, 415 Unsupported Media Type

I'm having trouble mapping a JSON Post to a particular Java Object to save it via Hibernate

Headers of the Ajax call are correctly set...

Accept          application/json
Content-Type    application/json; charset=UTF-8

and the HTTP-Method is POST

Here comes my configuration...

My Spring MVC function mapping looks like this

@RequestMapping(value = {"/save.json"},method = RequestMethod.POST)
public ModelMap save(@RequestBody Seizure seizureObj,Model model) {
   ...
}

in my container xml I have a ContentNegotiatingViewResolver like this

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="html" value="text/html" />
            <entry key="json" value="application/json" />
        </map>
    </property>
    <property name="viewResolvers">
        <list>
            <bean id="viewResolver"
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/assets/" />
                <property name="suffix" value=".jsp" />
            </bean>
        </list>
    </property>
    <property name="defaultViews">
        <list>
            <bean
                class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
                <property name="prefixJson" value="false" />
                <property name="objectMapper" ref="jacksonObjectMapper" />
            </bean>
        </list>
    </property>
</bean>

in my container xml the part for jackson

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterConfigurer"
    init-method="init">

    <property name="messageConverters">
        <list>
            <bean id="marshallingHttpMessageConverter"
                class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"
          >
          <property name="objectMapper" ref="jacksonObjectMapper" />
          </bean>
        </list>
    </property>
</bean> 

<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" /> 

I have

  • jackson-core-asl-1.8.5
  • jackson-mapper-asl-1.8.5

in my /lib folder

and Jackson works for a simple case like this

public class Simple {
  private int id;

  public int getId() {
    return id;
  }

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

@RequestMapping(value = {"/saveSimple.json"},method = RequestMethod.POST)
public ModelMap save(@RequestBody Simple simple,Model model) {
   ...
}

when I test it with curl

 curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"id":1}'  http://<URL>/saveSimple.json

No problems, but if I test it with the Hibernate object I get the message

415 Unsupported Media Type

any ideas.

like image 466
Jeremy S. Avatar asked Aug 22 '11 17:08

Jeremy S.


1 Answers

StanMax lead my in the right direction...

First I had to set the @JsonManagedReference and @JsonBackReference right. I set the ManagedReference to the attribute which represents the ONE of of the ONE-to-MANY relationship, but apparently you have to set it to the MANY attribute (the collection)

see the description here http://wiki.fasterxml.com/JacksonFeatureBiDirReferences

@JsonBackReference is the "back" part of reference: it will be omitted from serialization, and re-constructed during deserialization of forward reference.

  • Annotated property must be of bean type

The problem in my case was that I didn't send sufficient information in my JSON POST to match the Hibernate requirements.

This resulted in an Exception that the proper fields to create a Hibernate object out of my JSON POST, were not present.

I created a test url where I created the Object mapper myself and tried to de-serialize JSON by hand. This throw the right error message.

It seems to my that Spring unfortunately throws the 415 "Unsupported Media Type" exception which is a bit misleading.

So for the future. Try it out by hand first (see example included) and than go on.

 ModelMap map = new ModelMap();
 logger.info("HibernateAware");
 HibernateAwareObjectMapper mapper = new HibernateAwareObjectMapper();
 String jsonInput = 
 "{" +
   "\"id\":\"1\"," +
   "\"matCountry\":{" +
     "\"id\":\"1\"" +
   "}" +
 "}";
 Seizure seizure = mapper.readValue(jsonInput, Seizure.class); // this line throw the exception

Hope this helps someone.

Regards JS

like image 107
Jeremy S. Avatar answered Sep 24 '22 02:09

Jeremy S.