3

I am using spring 3.1, and my application is already set up to send and receive data in json format. Now I need to provide one request API that should return the same data but in xml format. Please help me with this stuff or tell what I am doing wrong. I tried JAXB, but instead of xml I receive "406 Not Acceptable".

My requests API:

/** 
* Gets objects in json format
*/
@RequestMapping(value = "/objects/json", method = RequestMethod.GET)
@ResponseBody
public List<MyObjectTO> getAll() {
    List<MyObjectTO> objectsList = new ArrayList<MyObjectTO>();
    //forming objects
    return objectsList;
}
/** 
* Gets objects in xml format
*/
@RequestMapping(value = "/objects/xml", method = RequestMethod.GET,headers={"Accept=application/xml"})
@ResponseBody
public ResponseList getAll() {
    ResponseList objectsList = new ResponseList ();
    //the same formation
    return objectsList;
}

Context

<?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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       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
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="com.kenshoo.urlbuilder"/>

    <mvc:annotation-driven/>
    <mvc:view-controller path="/mainpage" view-name="mainpage"/>
    <util:properties id="addProps" location="classpath:config/addProps.properties"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="alwaysUseFullPath" value="true"/>
    </bean>

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="html" value="text/html"/>
                <entry key="json" value="application/json"/>
                <entry key="pdf" value="application/pdf"/>
            </map>
        </property>
        <property name="viewResolvers">
            <list>
                <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="cache" value="true"/>
                    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
                    <property name="prefix" value="/WEB-INF/jsp/"/>
                    <property name="suffix" value=".jsp"/>
                </bean>
            </list>
        </property>

        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
            </list>
        </property>
    </bean>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
</beans>

My changes: Added message converters to AnnotationMethodHandlerAdapter and inserted JAXB marshaller. But after this got response "406 Not Acceptable":

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="alwaysUseFullPath" value="true"/>
    <property name="messageConverters">
       <list>
            <ref bean="marshallingConverter" />
       </list>
   </property>
</bean>

<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
     <property name="marshaller" ref="jaxbMarshaller" />
      <property name="unmarshaller" ref="jaxbMarshaller" />
      <property name="supportedMediaTypes" value="application/xml"/>
</bean>

<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
          <list>
            <value>com.ResponseList</value>
          </list>
    </property>
</bean>

I would appreciate any help, thanks.

UPDATE ResponseList structure:

public class ResponseList {

    private List<FirstLevel> firstLevelObjects;

    public List<FirstLevel> getFirstLevelObjects() {
        return firstLevelObjects;
    }

    public void setFirstLevelObjects(List<FirstLevel> firstLevelObjects) {
        this.firstLevelObjects= firstLevelObjects;
    }

}

FirstLevel structure:

public class FirstLevel {
    List<SecondLevel> secondLevelObjects; 
    boolean isConditional;
    String beforeStart;
    ConditionType type;//enum object
    //...getters and setters
}
me1111
  • 1,127
  • 3
  • 26
  • 38
  • What issue did you hit when you used JAXB? – bdoughan Jan 30 '13 at 10:16
  • I lost hope with Castor, so tried once more with JAXB. Changed post with details for JAXB. The same issues - I got Not Acceptable when trying to request xml. Can you help me? – me1111 Feb 12 '13 at 14:52
  • What does the Java model look like that you are converting to XML? – bdoughan Feb 12 '13 at 15:36
  • ResponseList has a list of objects, each has complex structure - lists of other classes, enums, boolean and strings. I updated post with structure – me1111 Feb 12 '13 at 15:52

1 Answers1

2

I lost hope with Castor, so tried once more with JAXB. Changed post with details for JAXB. The same issues - I got Not Acceptable when trying to request xml. Can you help me?

All you should need to do for JAXB is to add an @XmlRootElement annotation to your ResponseList class.

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class ResponseList {

    private List<FirstLevel> firstLevelObjects;

    public List<FirstLevel> getFirstLevelObjects() {
        return firstLevelObjects;
    }

    public void setFirstLevelObjects(List<FirstLevel> firstLevelObjects) {
        this.firstLevelObjects= firstLevelObjects;
    }

}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thanks, this works even if I remove all additional configs from my web-context.xml. Is this some kind of built-in HttpMessageConverter? Will I be able to use this object to receive json after this? – me1111 Feb 12 '13 at 16:25
  • 1
    @me1111 - If your JSON-binding implementation does not process JAXB annotations then there is no impact at all to adding the `@XmlRootElement` annotation. If the JSON provider does process JAXB annotations then there is probably config you can do to ignore it. – bdoughan Feb 12 '13 at 16:28
  • Thanks a lot, just using this tag very helped. Maybe you can tell if there is something more trivial to convert java array list of object to xml? Not nesseccary by the means of spring – me1111 Feb 12 '13 at 16:58
  • 1
    @me1111 - You may find the following useful: http://stackoverflow.com/a/13273022/383861 – bdoughan Feb 12 '13 at 18:43