SyntaxHighlighter

Wednesday, April 17, 2013

Spring WebMVC - returning XML instead of JSON using XStream

Spring WebMVC - returning XML instead of JSON using XStream

here's a little set of code i put together in response to a stackoverflow question (http://stackoverflow.com/questions/16060973/configuring-spring-mvc-rest-to-return-only-xml/160621420)

here's the entity that i'm going to expose

package de.incompleteco.spring.domain;

import java.io.Serializable;

public class SimpleEntity implements Serializable {

 private Long id;
 
 private String stuff;
 
 public SimpleEntity() {
  this.id = System.currentTimeMillis();
 }

 public Long getId() {
  return id;
 }

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

 public String getStuff() {
  return stuff;
 }

 public void setStuff(String stuff) {
  this.stuff = stuff;
 }
 
 
 
}


here's the very simple controller

package de.incompleteco.spring.web.controller;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import de.incompleteco.spring.domain.SimpleEntity;

@Controller
@RequestMapping("/simpleEntity")
public class SimpleRestController {

 
 @RequestMapping(method=RequestMethod.GET,produces=MediaType.APPLICATION_XML_VALUE)
 public @ResponseBody SimpleEntity get() {
  return new SimpleEntity();
 }
 
}



here's the xml way of wiring it up to use XStream as the XML Streaming engine


 
  
   
    
    
    
     
      #{T(org.springframework.http.MediaType).APPLICATION_XML_VALUE}
     
    
   
  
 
 
 

 





here's the @Configuration way to do the same

package de.incompleteco.spring.web;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.oxm.support.AbstractMarshaller;
import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
@ComponentScan("de.incompleteco.spring.web")
public class SimpleConfiguration extends WebMvcConfigurerAdapter {
 
 private XStreamMarshaller marshaller;
 
 @Override
 public void configureMessageConverters(List> converters) {
  converters.add(getHttpMessageConverter());
  super.configureMessageConverters(converters);
  
 }

 public HttpMessageConverter getHttpMessageConverter() {
  MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter();
  converter.setMarshaller(marshaller());
  converter.setUnmarshaller(marshaller());
  return converter;
 }

 @Bean
 public AbstractMarshaller marshaller() {
  if (marshaller == null) {
   return new XStreamMarshaller();
  } else {
   return marshaller;
  }
 }
 
}



and here's the tests for the code.
package de.incompleteco.spring.web.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({"classpath:/META-INF/spring/servlet-context.xml"})
public class SimpleRestControllerTest {

 @Resource
 private WebApplicationContext context;
 
 @Test
 public void testGet() throws Exception {
  MockMvc mvc = webAppContextSetup(context).build();
  //test
  MvcResult result = mvc.perform(get("/simpleEntity").contentType(MediaType.TEXT_HTML)).andExpect(status().isOk()).andReturn();
  //now show the context
  System.out.println(result.getResponse().getContentAsString());
 }

}



and
package de.incompleteco.spring.web.controller;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.web.context.WebApplicationContext;

import de.incompleteco.spring.web.SimpleConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes=SimpleConfiguration.class)
public class ConfigSimpleRestControllerTest {

 @Resource
 private WebApplicationContext context;
 
 @Test
 public void testGet() throws Exception {
  MockMvc mvc = webAppContextSetup(context).build();
  //test
  MvcResult result = mvc.perform(get("/simpleEntity").contentType(MediaType.TEXT_HTML)).andExpect(status().isOk()).andReturn();
  //now show the context
  System.out.println(result.getResponse().getContentAsString());
 }

}


one thing to note: you'll need to comment out/keep the @Configuration separate from the XML - the XML scans and hits the @Configuration annotation and tries to an appcontext inside and appcontext (and dies)

and here's the pom too...

  4.0.0
  de.incompleteco.spring.webmvc
  spring-webmvc-rest-xml
  0.0.1-SNAPSHOT
  war
  spring-webmvc-rest-xml
  
   
     
       org.apache.maven.plugins
       maven-compiler-plugin
       
         1.7
         1.7
       
     
      
    
  
   
    org.springframework
    spring-webmvc
    3.2.1.RELEASE
   
   
    org.springframework
    spring-test
    3.2.1.RELEASE
    test
   
   
    junit
    junit
    4.10
    test
   
   
    javax.servlet
    javax.servlet-api
    3.0.1
    provided
   
   
    org.springframework
    spring-web
    3.2.1.RELEASE
   
   
    log4j
    log4j
    1.2.17
    test
   
   
    org.springframework
    spring-oxm
    3.2.1.RELEASE
   
   
    com.thoughtworks.xstream
    xstream
    1.4.4
   
  

1 comment: