Reputation: 40160
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 makes a difference.
Thanks.
Upvotes: 14
Views: 15617
Reputation: 101
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>
Upvotes: 10
Reputation: 24666
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.
Upvotes: 2
Reputation: 7
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;
}
Upvotes: 0
Reputation: 51
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>
Upvotes: 5