6

I've implemented a RESTful web service with Spring. The service responds in XML or JSON based on the Accept header. Here's the context.xml mapping:

  <bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
  <bean id="xmlMessageConverter"
        class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
    <constructor-arg ref="xstreamMarshaller"/>
    <property name="supportedMediaTypes" value="application/xml"/>
  </bean>

  <bean id="jsonHttpMessageConverter"
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
    <property name="prefixJson" value="false"/>
    <property name="supportedMediaTypes" value="application/json"/>
  </bean>

  <bean
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters">
      <util:list id="beanList">
        <ref bean="xmlMessageConverter"/>
        <ref bean="jsonHttpMessageConverter"/>
      </util:list>
    </property>
  </bean>

Here is my controller method:

@Controller
@RequestMapping(value = "/entityService")
class RestfulEntityService {

  @Resource
  private EntityService entityService;

  @ResponseBody
  @RequestMapping(value = "/getAllEntities", method = RequestMethod.GET)
  public List<Entity> getAllEntities() {
    return entityService.getAllEntities();
  }
}

The XML response is valid, however, when the client sets the Accept header to application/json, the response is invalid JSON.

Here is the JSON response sample:

[{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes":[{"id":18,"attributeValue":null,"attributeName":"mobile","attributeType":"varchar(40)","entity":{"id":3,"attributes": ..... repeats for a while and then stops..
Sri
  • 5,805
  • 10
  • 50
  • 68
  • Might be worth posting a full valid and full invalid response – Mark Pope Apr 10 '11 at 17:55
  • Invalid response is huge (so is the valid response) because it has to serialize a list of 100 entities. The invalid response I have posted just gets repeated a hundred times and stops.. – Sri Apr 10 '11 at 17:56
  • Interestingly a small list with one or two entities gets serialized into JSON properly.. – Sri Apr 10 '11 at 17:58

1 Answers1

12

You're using XStream to serialize XML responses and Jackson JSON to serialize JSON responses. Looking at the JSON output you posted, it seems like there's a circular reference issue at hand. I'm guessing Entity has a list of attributes, each pointing to their respective entity. XStream handles circular references transparently by using XPath, this allows to preserve references when deserializing back to objects. Jackson is able to handle circular references since v1.6, but you need to help it by annotating your serialized entities with @JsonManagedReference and @JsonBackReference. I think Jackson is unique in allowing back references in JSON serialization.

See Jackson's documentation on handling bi-directional references using declarative methods for reference.

Ophir Radnitz
  • 1,783
  • 2
  • 20
  • 18