0

I want to generate a json object using @ResponseBody in the controller. but what i'm getting at browser side is: status 406 "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers."

Below is the pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.anand</groupId>
  <artifactId>AnandWebStore</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>AnandWebStore Maven Webapp</name>
  <url>http://maven.apache.org</url>

 <properties>
        <spring.version>4.0.3.RELEASE</spring.version>
        <hibernate.core>4.2.7.Final</hibernate.core>
    </properties>

 <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
        <!-- Spring dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>  


         <dependency>
               <groupId>org.springframework</groupId>
               <artifactId>spring-orm</artifactId>
               <version>${spring.version}</version>
         </dependency>
         <dependency>
               <groupId>org.springframework</groupId>
               <artifactId>spring-jms</artifactId>
               <version>${spring.version}</version>
         </dependency>


        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.0.0.GA</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.0.2.GA</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>


        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.6</version>
        </dependency>

        <dependency>
           <groupId>commons-fileupload</groupId>
           <artifactId>commons-fileupload</artifactId>
           <version>1.3</version>
        </dependency>

        <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
                <version>${hibernate.core}</version>
        </dependency>

        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4-2.0</version>
        </dependency>

         <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.webflow</groupId>
            <artifactId>spring-js-resources</artifactId>
            <version>2.4.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.7.4</version>
        </dependency>

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



  </dependencies>
  <build>
    <finalName>AnandWebStore</finalName>
  </build>
</project>

I have used jackson-core-asl & jackson-mapper-asl with 1.7.4 version.

Below is the piece of code in jsp that post the data to the controller.

<form:form class="well form-horizontal" action="saveCustomer.html" method="post"  id="contact_form" commandName="customer">
        <fieldset>

            <div class="form-group">
                <label class="col-md-4 control-label">First Name</label>  
                <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                        <form:input  path="first_name" name="first_name" placeholder="First Name" class="form-control"  type="text" />
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label" >Last Name</label> 
                <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                        <form:input path ="last_name" name="last_name" placeholder="Last Name" class="form-control"  type="text" />
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">E-Mail</label>  
                <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
                        <form:input path="email" name="email" placeholder="E-Mail Address" class="form-control"  type="text" />
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">Phone #</label>  
                <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-earphone"></i></span>
                        <form:input path ="phone" name="phone" placeholder="(845)555-1212" class="form-control" type="text"/>
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">Address</label>  
                    <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                        <form:input path="address" name="address" placeholder="Address" class="form-control" type="text"/>
                    </div>
                </div>
            </div>

            <div class="form-group">
                <label class="col-md-4 control-label">City</label>  
                <div class="col-md-4 inputGroupContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                        <form:input path="city" name="city" placeholder="city" class="form-control"  type="text"/>
                    </div>
                </div>
            </div>

            <div class="form-group"> 
                <label class="col-md-4 control-label">State</label>
                <div class="col-md-4 selectContainer">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-list"></i></span>
                        <form:select path="state" name="state" class="form-control selectpicker">
                            <option value=" " >Please select your state</option>
                            <option>......</option>
                        </form:select>
                    </div>
                </div>
            </div>

            <div class="alert alert-success" role="alert" id="success_message">Success <i class="glyphicon glyphicon-thumbs-up"></i> Customer Added Successfully...</div>

            <div class="form-group">
                <label class="col-md-4 control-label"></label>
                <div class="col-md-4">
                    <button type="submit" class="btn btn-warning" >Add <span class="glyphicon glyphicon-send"></span></button>
                </div>
            </div>

        </fieldset>
    </form:form>

Below is the code for dispatcher servlet:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    ">

    <mvc:annotation-driven/>
    <mvc:resources location="/resources/" mapping="/resources/**" />
    <context:component-scan base-package="com.anand" />
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages" />
    </bean>

</beans>

i have used <mvc:annotation-driven/> here.

below is the code for controller:

package com.anand.controllers;

import java.util.HashMap;
import java.util.Map;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.anand.forms.CustomerForm;
import com.anand.forms.LoginForm;
import com.anand.model.Customer;
import com.anand.services.CustomerService;

@Controller
public class CustomerController {

    private static final Logger logger = LoggerFactory.getLogger(CustomerController.class);

    @Autowired
    private CustomerService customerService;

    @RequestMapping(value="saveCustomer.html",method=RequestMethod.POST)
    private @ResponseBody Map<String, Object>saveCustomer(@Valid Customer customer, BindingResult result)
    {
        if(result.hasErrors())
        {

        }
        boolean saveFlag = customerService.save(customer);
        Map<String, Object> map = new HashMap<String, Object>();
        if(saveFlag==true)
        {
            map.put("status", 200);
            map.put("Message", "Data for customer saved successfully");
        }
        else
        {
            map.put("status", 500);
            map.put("Message", "Error occured at server side");
        }
        return map;
    }
}

Note: Here i can see that the posted data from the UI is getting stored in the DB and i can see the hibernate query executed for the same in the eclipse console as well but at ui side i'm getting error 406. I have analyzed the network part of the brwoser and found below information:

Request Headers:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:126
Content-Type:application/x-www-form-urlencoded
Cookie:JSESSIONID=A343E5E9FBF5866A12CEC2703DD5A5AE
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/AnandWebStore/forms/loginform.html
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36

From the answers ofseveral question in stackoverflow i got to know that the problem is with below line and this header should be like application/json:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

yes that is fine . but how to resolve this??

Happy Porwal
  • 61
  • 1
  • 8
  • jackson 1.7 ? check fasterxml jackson , it's currently the 2.8 version. Or Are you stuck with that one ? – Walfrat Jan 10 '17 at 19:54
  • whgat do you use as front client ? a browser ? – Walfrat Jan 10 '17 at 19:55
  • @Walfrat yes it's a browser...i also tried to use postMan chorme extension to check the response body. – Happy Porwal Jan 10 '17 at 19:57
  • @Walfrat yes it's a browser...i also tried to use postMan chorme extension to check the response body and i'm not aware the best among the fasterxml & codehaus Jackson...some where i got that we have to use jackson library for responsebody and then i have searched for it and found codehaus jackson lib and used it and updated to the latest version that is 1.9.13 – Happy Porwal Jan 10 '17 at 20:07
  • fasterxml is a fork from codehaus andas far i know it's the official jackson now – Walfrat Jan 10 '17 at 20:17
  • how you are sending request to server? is it ajax? or form post on click of submit? – ScanQR Jan 11 '17 at 07:38
  • I don't know if Spring 4.03 still supports Jackson 1.7.4. I suggest to upgrade to a more recent version anyway. Also add `produces="application/json"` to your `@RequestMapping` if you want to return JSON. – a better oliver Jan 11 '17 at 11:46
  • @ScanQR it is post on click of submit. – Happy Porwal Jan 11 '17 at 18:43
  • @Walfrat--i have made some changes to the approch.....instead of using form submit. I have switched to AJAX and tried the same but again i got the same issue. Then i swithced to fasterXml as suggested by you and it's working now. Thanks for all your help. – Happy Porwal Jan 21 '17 at 18:49

5 Answers5

0

It is a little bit confusing - You want to send HTML form POST request and get JSON as response? I really recommend you to decide if you want to proceed entire request with form and HTML response, or with JSON. It will be more clear and user friendly

But if you really want to consume form and produce JSON (which does not make sense for me), send your form using XMLHttpRequest in javascript, or use other JS library such as jQuery and add header with application/json. It is not possible to send JSON request using HTML form. Accepted types are listed here

What I recommend is to consume and produce HTML, or produce and consume JSON. If you decide for JSON remember to add @RequestBody annotation near controller parameter. So it will look like

 @RequestMapping(value="saveCustomer.html",method=RequestMethod.POST)
private @ResponseBody Map<String, Object>saveCustomer(@Valid @ReqyuestBody Customer customer, BindingResult result)
{ ....

Hope it helps

shark
  • 995
  • 1
  • 8
  • 19
  • Update: I switched to AJAX call and replaced codehus-Jackson libraries to fasterXml-jackson libraries and it start working for me. I got the clue from the 'Paul grime''s answer to this http://stackoverflow.com/questions/7473498/spring-mvc-406-not-acceptable-instead-of-json-response. " "In terms of the MappingJacksonJson processing, you'll need to make sure that the Jackson ObjectMapper supports your object type for serialisation." -->From this i got the clue to use FasterXml-Jackson instead of codehus-Jackson. Again thanks for your help. – Happy Porwal Jan 21 '17 at 19:06
0

If you want to return a json object, you need to return a ResponseEntity instead from your controller:

return new ResponseEntity<Map<String, String>>(map, HttpStatus.OK);
Taf
  • 258
  • 2
  • 8
0

Try something like this

@RequestMapping(value = "saveCustomer.html",
        method = RequestMethod.POST,
        consumes= { "application/json" },
        produces = { "application/json" })
    public ResponseEntity<String> saveCustomer(@Valid Customer customer, BindingResult result) {

    // your business logic here

    if(saveFlag==true) {
        return new ResponseEntity<String>("Data for customer saved successfully", HttpStatus.OK);   
    }
    else {
        return new ResponseEntity<String>("Error occured at server side", HttpStatus.INTERNAL_SERVER_ERROR);            
    }

}
  • Thanks for answering the question. But i have tried to use the same but it is not working i got Status code - 415 with the decription as 'The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.' – Happy Porwal Jan 11 '17 at 18:38
0

As you are doing HTML Form POST on Submit you need to define enctype attribute as follows,

<form enctype='application/json'>

This will allow your user agent to process the json response.

ScanQR
  • 3,740
  • 1
  • 13
  • 30
  • Hi i tried the same but it was not working for me then i have switched to AJAX call and replaced codehus-Jackson libraries to fasterXml-jackson libraries and it start working for me. I got the clue from the 'Paul grime''s answer to this http://stackoverflow.com/questions/7473498/spring-mvc-406-not-acceptable-instead-of-json-response. " "In terms of the MappingJacksonJson processing, you'll need to make sure that the Jackson ObjectMapper supports your object type for serialisation." -->From this i got the clue to use FasterXml-Jackson instead of codehus-Jackson. Again thanks for your help. – Happy Porwal Jan 21 '17 at 18:54
0

Finally it's working now.First I have changed approach to do the same. Now instead of using form submit i'm using Ajax call as below:

$('#AddCustButton').click(function(){

        var firstName = $('#first_name').val();
        var lastName = $('#last_name').val();
        var email = $('#email').val();
        var phone = $('#phone').val();
        var address = $('#address').val();
        var city = $('#city').val();
        var state = $('#state').val();


        $.ajax({
            url:'saveCustomer',
            type:'POST',
            dataType:'json',
            data:{'first_name':firstName,'last_name':lastName,'email':email,'phone':phone,'address':address,'city':city,'state':state},
            success:function(response){
                if(response.status=='Success'){
                    $('#success_message').slideDown({ opacity: "show" }, "slow"); // Do something ...
                    $('#contact_form').data('bootstrapValidator').resetForm();
                }
            }
        });
    });

And then checked for the response but was getting the same error with status code 406.Then i got a clue to change the Codehus-Jackson libraries to FasterXml-Jackson From the comments of @Walfrat(see comments below the question) and from the 'Paul grime''s answer to this question Question

After Changing from codehaus-Jackson to fasterXML-Jackson it's working.

Community
  • 1
  • 1
Happy Porwal
  • 61
  • 1
  • 8