开发者

Spring MVC @ResponseBody returning a Map produces "Error 406 NOT ACCEPTABLE"

开发者 https://www.devze.com 2023-04-03 01:33 出处:网络
I\'m having a problem trying to set up @ResponseBody to return a collection. I have JAXB jars in the classpath and I didn\'t set up any ContentNegotiatingViewResolver.

I'm having a problem trying to set up @ResponseBody to return a collection. I have JAXB jars in the classpath and I didn't set up any ContentNegotiatingViewResolver.

This is my simple object:-

@XmlRootElement(name = "test-object")
@XmlAccessorType(XmlAccessType.FIELD)
public class TestObject implements Serializable {

    @XmlAttribute
    private int id;

    public int getId() {
        return id;
    }

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

I wrote a simple test that returns a single object... this works without problem, and I'm able to see the generated XML:-

@RequestMapping(value = "one", method = RequestMethod.GET)
public @ResponseBody TestObject getSingleObject() {
    TestObject obj = new TestObject();
    obj.setId(1);

    return obj;
}

What I really want is to return a list of objects. After reading around, it seems like the way to do so is to place the list in a map and return the map:-

@RequestMapping(value = "all", method = RequestMethod.GET)
public @ResponseBody Map<String, ? extends Object> getAllObjects() {
    TestObject obj1 = new TestObject();
    obj1.setId(1);

    TestObject obj2 = new TestObject();
    obj2.setId(2);

    List<TestObject> list = Arrays.asList(obj1, obj2);

    return Collections.singletonMap("all-objects", list);
}

When I execute the above, I'm getting "Error 406 Not Acceptable".

What did I do wrong here? I'm running on Jetty 6.1 if that make开发者_开发百科s a difference.

Thanks.


You need these two dependencies added in the pom.xml!

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-lgpl</artifactId>
    <version>1.8.1</version>
</dependency>

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-lgpl</artifactId>
    <version>1.8.1</version>
</dependency>


I had the same problem and after a couple of hours of debugging I finally found the solution. Just in case someone else get stuck with the same problem, this is what I found.

You probably followed Ajax Simplifications in Spring 3 which tells you to use the mvc:annotation-driven configuration element.

What it doesn't tell you is that mvc:annotation-driven is just a shortcut to define a couple of standard beans, unless you already have one of those beans defined!

With the mvc:annotation-driven configuration a MappingJacksonHttpMessageConverter is registered as a messageConverter on a org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.

If you have defined your own AnnotationMethodHandlerAdapter, you should also manually define this MappingJacksonHttpMessageConverter .

Cfr Custom message converters registered with AnnotationMethodHandlerAdapter are not used, only the default ones are used. which discusses a similar issue. Also check SPR-6524 and SPR-6306, can't post links due to spam prevention :(

The relevant part in my spring config ended up looking like this:

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="webBindingInitializer">
            <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
                <property name="validator">
                    <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
                    </bean>
                </property>
            </bean>
        </property>
         <property name="messageConverters">
            <list>   
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.feed.RssChannelHttpMessageConverter"/>
            </list>
        </property>
</bean>


I know this question is a bit old, but I had the same problem.

I solved adding to build path two jars: jackson-core-asl-1.x.jar and jackson-mapper-asl-1.x.jar. You can download them from here: http://wiki.fasterxml.com/JacksonDownload or if you use Maven you can add them as projet dependency.

Note that I used version 1.x (1.9, in my case) and not 2.x. Last version didn't work for me.


More of a suggestion than an answer, but have you tried to create the map and then add the object and then just return the map like this?

@RequestMapping(value = "all", method = RequestMethod.GET)
public @ResponseBody Map<String, ? extends Object> getAllObjects() {
    TestObject obj1 = new TestObject();
    obj1.setId(1);

    TestObject obj2 = new TestObject();
    obj2.setId(2);

    List<TestObject> list = Arrays.asList(obj1, obj2);
    Map<String, Object> map = new TreeMap<String, Object>();
    map.put("all-objects",list);
    return map;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号