26

I am using Spring MVC with JSON as specified in Ajax Simplification Spring 3.0 article.

After so many attempts and variations of my code depending on advice found on various forums, my code still doesn't work.

I keep on getting the following error: (406) The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers ().

I have in my appconfig.xml as required.

app-config.xml

    <context:component-scan base-package="org.ajaxjavadojo" />

    <!-- Configures Spring MVC -->
    <import resource="mvc-config.xml" />

mvc-config.xml

<mvc:annotation-driven />

<!-- Forwards requests to the "/" resource to the "index" view -->
<mvc:view-controller path="/" view-name="index"/>


<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
<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 class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</list>
</property>

</bean>

This is what I have for my controller

@Controller
@RequestMapping (value = "/convert")
public class ConversionController {

  @RequestMapping(method=RequestMethod.GET)
  public String getConversionForm(){
    return "convertView";
  }

  @RequestMapping(value = "/working", headers="Accept=application/json", method=RequestMethod.GET)
  public @ResponseBody Conversion getConversion(){
    Conversion d = new Conversion("d");
    return d;
  }
}

jsp jquery call

  function convertToDecimal(){
    $.getJSON("convert/working", {key: "r"}, function(aConversion){
      alert("it worked.");
      $('#decimal').val(aConversion.input);
    });
  }

I would really appreciate any input on this issue. Thank you

Marplesoft
  • 6,030
  • 4
  • 38
  • 46
serena
  • 303
  • 1
  • 5
  • 10

14 Answers14

23

To return JSON response from @ResponseBody-annotated method, you need two things:

You don't need ContentNegotiatingViewResolver and headers in @RequestMapping.

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • I have removed the ContentNegotiatingViewResolver and headers information but it is still not working. When you say on the classpath, does it mean I have to import jackson's libraries? If so I have them included. – serena Nov 01 '10 at 20:02
  • Then threre is on unclear thing in your question: how is `app-config.xml` related to DispatcherServlet's `...-servlet.xml` config? – axtavt Nov 01 '10 at 20:16
  • in web.xml, i specify the servlet, then app-config.xml (contextConfigLocation) : dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/app-config.xml 1 – serena Nov 01 '10 at 20:26
  • This was my issue! I had jackson-mapper-lgpl. I needed to change that to artifactId jackson-mapper-lgpl. – Alex May 18 '12 at 11:34
  • @atc Kindly explain me what you did – Ram Apr 15 '13 at 08:58
  • @atc Initial and final value for artifactId is same – Ram Apr 15 '13 at 09:05
  • 1
    Adding the jackson json mapper to my maven dependencies was the correct solution for me - vote++ – Dieter Hubau Jul 24 '13 at 16:14
  • Dude your idea was freaking awesome! I was using Spring Guide "how to build rest-service" from: http://spring.io/guides/gs/rest-service I couldn't get through 406 without jackson-mapper-asl. I thought that guide from official Spring Site will be complete but unfortunately it was not. THANKS AGAIN! – bpawlowski Oct 29 '13 at 19:28
  • I have added jackson-mapper-asl to my maven dependencies. I see the 2 jackon jars listed in my Maven Dependencies leading me to think I have done this correctly. But, I still get the 406. What am I missing? – Doo Dah Mar 30 '14 at 22:46
  • Maven dependency which saved me: org.codehaus.jackson jackson-mapper-asl 1.9.13 – Spiff Jul 17 '14 at 12:02
18

I had this problem after I upgraded Spring to 4.1.x from 3.2.x. I fixed by upgrading Jackson from 1.9.x to 2.2.x (fasterxml)

 <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.2.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.2.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.2.3</version>
</dependency>
jprism
  • 3,239
  • 3
  • 40
  • 56
9

Try remove the header limitation for Accept, put a breakpoint and see what's the actual value. Or do this with FireBug.

Also take a look at this jquery issue

Jens
  • 67,715
  • 15
  • 98
  • 113
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 3
    Thank you so much. According to the article the accept header should be set to */*. so i updated the request mapping to: @RequestMapping(value = "/working", headers="Accept=*/*", method=RequestMethod.GET) and now it works :)) – serena Nov 01 '10 at 20:12
8

Add org.springframework.http.converter.json.MappingJacksonHttpMessageConverter and org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter to DispatcherServlet-servlet.xml. and refer to the the first one in the second using

<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
        <list>
            <ref bean="jacksonMessageConverter"/>
        </list>
    </property>
</bean>
Thomas
  • 4,119
  • 2
  • 33
  • 49
  • Thanks a lot, this worked for me! Only change is to rename MappingJacksonHttpMessageConverter to MappingJackson2HttpMessageConverter in your snippet which is what is in latest spring version - 4.2.0.RELEASE – vanval Feb 11 '16 at 22:56
3

I too got this error and while debugging deep down into the rabbit hole i came across this exception

java.lang.IllegalArgumentException: Conflicting getter definitions for property "error": com.mycomp.model.OutputJsonModel#isError(0 params) vs com.mycomp.model.OutputJsonModel#getError(0 params)

So basically in my java bean i had something like the following:

private boolean isError;
private ErrorModel error;

public ErrorModel getError() {
return error;
}

public void setError(ErrorModel error) {
this.error = error;
}
public boolean isError() {
return isError;
}

public void setError(boolean isError) {
this.isError = isError;
}

Changing one of the error member variable name to something else solved the issues.

user320550
  • 1,093
  • 6
  • 20
  • 37
2

I had this problem too, you have to add <mvc:annotation-driven /> in your configuration xml

and

<!-- Jackson -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.databind-version}</version>
        </dependency>

in your pom.xml

Stefanos T.
  • 550
  • 5
  • 7
2

I have used java configuration and i got this same error. I have missed to add the @EnableWebMvc to the configuration file. This error is resolved after i add the @EnableWebMvc in my webconfig file.

Also the Object that is returned from your Spring Controller, should have proper getter and setter methods.

package com.raghu.dashboard.config;

import org.springframework.context.annotation.Bean;
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.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.raghu.dashboard.dao.ITaskDAO;
import com.raghu.dashboard.dao.TaskDAOImpl;


    @Configuration
    @EnableWebMvc  //missed earlier...after adding this it works.no 406 error
    @ComponentScan(basePackages = { "com.raghu.dashboard.api", "com.raghu.dashboard.dao" })
    public class WebConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

        protected Class<?>[] getRootConfigClasses() { return null;}

        protected Class<?>[] getServletConfigClasses() {
            return new Class[] { MongoConfiguration.class};
        }

        protected String[] getServletMappings() {
            return new String[]{"*.htm"}; 
        }

        @Bean(name = "taskDao")
        public ITaskDAO taskDao() {
            return new TaskDAOImpl();
        }

        @Bean
        public InternalResourceViewResolver getInternalResourceViewResolver() {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix("/WEB-INF/pages/");
            resolver.setSuffix(".jsp");
            return resolver;
        }

    }

AppInitializer.java

package com.raghu.dashboard.config;

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

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
    public class AppInitalizer implements WebApplicationInitializer {

        @Override
        public void onStartup(ServletContext servletContext)
                throws ServletException {
            WebApplicationContext context = getContext();
            servletContext.addListener(new ContextLoaderListener(context));
            ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/*");
        }

        private AnnotationConfigWebApplicationContext getContext() {
            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
            context.register(com.raghu.dashboard.config.WebConfig.class);
            context.scan("com.raghu.dashboard.api");
            return context;
        }

    }

Also make sure the Object that is returned, has the proper getter and setter.

Example:

@RequestMapping(value = "/list", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<TaskInfo> findAll() {
    logger.info("Calling the findAll1()");
    TaskInfo taskInfo = dashboardService.getTasks();
    HttpHeaders headers = new HttpHeaders();
    headers.add("Access-Control-Allow-Origin", "*");
    ResponseEntity<TaskInfo> entity = new ResponseEntity<TaskInfo>(taskInfo,
            headers, HttpStatus.OK);
    logger.info("entity is := " + entity);
    return entity;
}

TaskInfo object should have proper getter and setter. if not, 406 error will be thrown.

POM File for Reference:

<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.raghu.DashBoardService</groupId>
    <artifactId>DashBoardService</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>DashBoardService Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <!-- Spring -->
        <spring-framework.version>4.0.6.RELEASE</spring-framework.version>
        <jackson.version>2.4.0</jackson.version>
        <jaxb-api.version>2.2.11</jaxb-api.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!-- Spring Data Mongo Support -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-mongodb</artifactId>
            <version>1.4.1.RELEASE</version>
        </dependency>

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

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

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

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

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

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

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

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


<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-dao</artifactId>
    <version>2.0.3</version>
</dependency>



        <!-- Jackson mapper -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.2.3</version>
        </dependency>

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

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>1.7.1</version>
        </dependency>

        <!-- Log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>1.5.0.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>DashBoardService</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
Raghu
  • 1,363
  • 1
  • 23
  • 37
1

issue is not related to jquery . even bug is saying it is server side issue . please make sure that following 2 jar present in class path :-

jackson-core-asl-1.9.X.jar jackson-mapper-asl-1.9.X.jar

skuntsel
  • 11,624
  • 11
  • 44
  • 67
Raju Rathi
  • 109
  • 1
  • 1
  • A version of this fixed it for me when I switched from 1.9.x jackson to 2.x (fasterxml). I had only imported core but not annotations or the data binding. I wasn't happy with removing the accept option. – Chanoch May 02 '14 at 15:32
1

I also faced this same issue and I downloaded this [jar]: (http://www.java2s.com/Code/Jar/j/Downloadjacksonall190jar.htm)! and placed in lib folder and the app works like a charm :)

1

See my answer to a similar problem here with Spring MVC interpreting the extension of the URI and changing the expected MIME type produced behind the scene, therefore producing a 406.

Community
  • 1
  • 1
Jérémie
  • 360
  • 5
  • 6
1

Well, The answers on this page might be right but they didn't expatiate well. This is what I did

I added this to my pom.xml

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

Then I added headers to my RequestMapping like below

@RequestMapping(value="/admin/getGallery", method = RequestMethod.GET, headers={"Content-Type=application/json"})

Then in my jquery ajax I added - contentType: "application/json", so it looks like

jQuery.ajax({
            type:'GET',
            url:"getGallery.html",
            data: "designId="+designId,
            processData:false,
            contentType: "application/json",
            //dataType: "json",
           success:function(data){
              console.log(data);

           },
            error : function(e) {
                console.log("ERROR: ", e);
            },
        });

Then in my servlet I added

<bean id="jsonHttpMessageConverter"
    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
    <!-- Bind the return value of the Rest service to the ResponseBody. -->
    <bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
    <util:list id="beanList">
    <ref bean="jsonHttpMessageConverter" />
    </util:list>
    </property>
</bean> 

If you have problem with util tag in your servlet just just add in the same servlet file

xmlns:util="http://www.springframework.org/schema/util"

and

xsi:schemaLocation="http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
Yinka
  • 1,741
  • 4
  • 15
  • 23
  • If Spring version >4 then you have to change class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter to class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter. As per http://www.andreagirardi.it/blog/mappingjacksonhttpmessageconverter-not-found/ – Nitish Patel Feb 08 '19 at 07:33
0

Instead of @RequestMapping(...headers="Accept=application/json"...) use @RequestMapping(... , produces = "application/json")

Axel Fontaine
  • 34,542
  • 16
  • 106
  • 137
Daniel David Kovacs
  • 226
  • 1
  • 2
  • 13
0

Using jQuery , you can set contentType to desired one (application/json; charset=UTF-8' here) and set same header at server side.

REMEMBER TO CLEAR CACHE WHILE TESTING.

0

As said by axtavt, mvc:annotation-driven and jackson JSON mapper are all that you need. I followed that and got my application to return both JSON and XML strings from the same method without changing any code, provided that there are @XmlRootElement and @XmlElement in the object you are returning from the controller. The difference was in the accept parameter passed in the request or header. To return xml, any normal invocation from the browser will do it, otherwise pass the accept as 'application/xml'. If you want JSON returned, use 'application/json' in the accept parameter in request.

If you use firefox, you can use tamperdata and change this parameter

Iceman
  • 11
  • 1