Spring MVC method handling json and form params

12,459

Solution 1

@RequestMapping (method = RequestMethod.POST)
public Book createBook(Book book)
        throws Exception {
    return book;
}

consumes takes a string array of whatever it can consume, spring bean binding should take care of the rest. The problem might be you haven't set up bean binding correctly in order to marshall and unmarshall json automaticaly. using @RequestBody and @RepsonseBody isn't the best option imho.

make sure jackson is added to your dependencies

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>latest</version>
</dependency>

and use a contentnegotiatingviewresolver

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="mediaTypes">
        <map>
            <entry key="htm" value="text/htm"/>
            <entry key="html" value="text/html"/>
            <entry key="json" value="application/json"/>
        </map>
    </property>
    <property name="viewResolvers">
        <list>
            <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/"/>
                <property name="suffix" value=".jsp"/>
            </bean>
        </list>
    </property>

    <property name="defaultViews">
        <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>

        </list>
    </property>
</bean>

make sure the accept headers are set in your client application to the needed values. You also should be able to drop all producing and consuming data in the requestmethod annotation

Solution 2

If you want spring to convert from JSON to your object automatically you will have to use @RequestBody. If you don't use it, the values will not be bound and all parameters are null as you described when sending in JSON.

If you use @RequestBody: Behind the scenes the conversion is done using MessageConverters, as described in the spring documentation: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestbody

You are correctly configuring the MappingJacksonHttpMessageConverter, which does the translation from JSON to your object.

What is missing is a translation from form data to your object: You have a FormHttpMessageConverter registered, but according to the documentation this does not what you expect it to do. It translates a request using x-www-form-urlencode to a MultiValueMap<String, String>and not to your custom object.

My current understanding is that you would have to write something similar to the MappingJacksonHttpMessageConverter but only capable of handling form data.

Share:
12,459
Chakravarthi Bharathi
Author by

Chakravarthi Bharathi

Updated on June 17, 2022

Comments

  • Chakravarthi Bharathi
    Chakravarthi Bharathi almost 2 years

    I want the handle the content types application/x-www-form-urlencoded and application/json in single spring mvc method.

    I've a requirement in rest service to accept input as form parameters or json. I can achieve this by writing two methods. Either form params or json, the response will be always json.

    @RequestMapping (method = RequestMethod.POST, produces = {"application/json"},
            consumes = {"application/x-www-form-urlencoded"})
    public @ResponseBody Book createBook(Book book)
            throws Exception {
        return book;
    }
    
    @RequestMapping (method = RequestMethod.POST, produces = {"application/json"},
            consumes = {"application/json"})
    public @ResponseBody Book createBookJSON(@RequestBody Book book)
            throws Exception {
        return book;
    } 
    

    Is it possible to combine these two methods into one and make it work? Any help will be much appreciated.

    Edit

    I've Implemented the same, my controllers and configuration are given below, but when I send json request I get null values as response.

    When I send the form params it is working fine. Help me to find out the issue.

    Controller method

     @RequestMapping (method = RequestMethod.POST, produces = {"application/json", "application/xml"}, consumes = {"application/x-www-form-urlencoded", "application/json"})                   
        public @ResponseBody Book createBook(Book book)
                throws Exception {
            return book;
        }
    

    servlet-context

    <mvc:view-controller path="/" view-name="index"/>
    
    <context:annotation-config />
    
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1" />
        <property name="mediaTypes">
            <map>
                <entry key="xml" value="application/xml" />
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <!-- JSON View -->
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
    
                <!-- JAXB XML View -->
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <constructor-arg>
                        <ref bean="jaxb2Marshaller" />
                    </constructor-arg>
                </bean>
    
            </list>
        </property>
        <property name="ignoreAcceptHeader" value="true" />
    </bean>
    
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
        <property name="order" value="1" />
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
                    <property name="supportedMediaTypes" value="application/json"/>
                </bean>
    
                <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller" ref="jaxb2Marshaller" />
                    <property name="unmarshaller" ref="jaxb2Marshaller" />
                    <property name="supportedMediaTypes" value="application/xml"/>
                </bean>
    
                <bean class = "org.springframework.http.converter.FormHttpMessageConverter">
                    <property name="supportedMediaTypes" value = "application/x-www-form-urlencoded" />
                </bean>
    
                <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
                </bean>
            </list>
        </property>
    </bean>
    
    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
        <property name="classesToBeBound">
            <list>
                <value>com.lt.domain.Book</value>
            </list>
        </property>
    </bean>
    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2" />
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>