How to POST XML using RestTemplate

15,242

You don't need to use Spring's JAXB marshalling message converter - you've already done the work by making it into a String. Just POSTing the String (like in your code) ought to work (lose the String.class argument though, that's intended for URL variables, and get rid of the setMessageConverters call, because that is preventing the default StringHttpMessageConverter from working).

Share:
15,242
zfranciscus
Author by

zfranciscus

I am a software developer and a writer for How-To Geek. You can find me tweeting at twitter or bookmarking interesting sites on delicious .

Updated on June 07, 2022

Comments

  • zfranciscus
    zfranciscus almost 2 years

    I intend to POST an XML message using Spring Rest Template. After a number of failures, I am starting to doubt whether Spring Rest Template can POST an XML message. This is a Restful client that I developed. The RestTemplate is intended to do an HTTP post of an XML to a RestFul webservice:

     Class RestClient{
        public static void main(String[] args) {
    
    RestTemplate restTemplate = new RestTemplate();
    
    
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    
        //This JAXB Message converter is intended to marshal an XML message over HTTP.
        //However, I find this converter is not doing the intended function.
    
        Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
        List<MediaType> mediaTypes = new ArrayList<MediaType>();
        mediaTypes.add(MediaType.TEXT_HTML);
        jaxbMessageConverter.setSupportedMediaTypes(mediaTypes);
    messageConverters.add(jaxbMessageConverter);
    restTemplate.setMessageConverters(messageConverters);
    restTemplate.postForLocation("http://localhost:8080/RecipeProject/restCallConsumer", "<add><somefield></somefield></add>",String.class);
       }
    

    }

    This controller is intended to consume the XML message. The controller was written to test that the client can send the XML message appropriately:

    @RequestMapping("/")
    @Controller
    public class HomeController {
    @RequestMapping(value = "/restCallConsumer", method = RequestMethod.POST)
    public String restCallConsumer(String anXML) {
    System.out.println("anXML: " + anXML);  
    return "aView";
     }
    }
    

    Most of the example I found around using XML with RestTemplate involves using an object mapping tool. This tool maps object to an XML and vice versa. In my case, I only have an XML string that I want to send via HTTP post. Has anyone accomplished what I am trying to do ? It could be that RestFul client is not intended for what I am trying to do. Any answer would be appreciated :)

    EDIT

    THe XML message is produced by serializing a Map using Xstream. This is the code that does that:

        com.google.common.collect.LinkedListMultimap.ListMultimap<String, String> multimap = com.google.common.collect.LinkedListMultimap.LinkedListMultimap.create();
    multimap.put("x", "1");
    multimap.put("x", "2");
    multimap.put("y", "3");
    
    XStream xStream = new XStream(new DomDriver());
    xStream.registerConverter(new MapEntryConverter(xStream.getMapper()));
    
    xStream.alias("add", multimap.getClass());
    String xml = xStream.toXML(multimap);
    System.out.println(xml);
    

    This code is intended to convert the multimap into an XML string using a converter named MapEntryConverter. This is the code for the Converter:

    public static class MapEntryConverter extends MapConverter {
    
    public MapEntryConverter(Mapper mapper) {
        super(mapper);
    }
    
    public boolean canConvert(Class clazz) {
        return ListMultimap.class.isAssignableFrom(clazz);
    }
    
    public void marshal(Object value, HierarchicalStreamWriter writer,
        MarshallingContext context) {
    
        ListMultimap<String, String> map = (ListMultimap<String, String>) value;
        for (String key : map.keys()) {
        writer.startNode(key);
        writer.setValue(map.get(key).get(0));
        writer.endNode();
        }
    }
    
    }
    

    EDIT

    I change my code as per @artbristol recommended. I saw this in the log file:

    DEBUG: org.springframework.web.client.RestTemplate - Writing [ 1 1 3 ] using [org.springframework.http.converter.StringHttpMessageConverter@1d34263a]

    It looks like the restTemplate is POST-ing the XML message. However, the anXML parameter in the controller is null. Does this mean that the XML message could not reach the controller ? Could it be that the controller is not implemented correctly ?

  • zfranciscus
    zfranciscus about 11 years
    It look like it works :) However, I could not print out the XML message in the controller. The XML message is null. I added more info in my question. Thank you @artbristol
  • artbristol
    artbristol about 11 years
    I noticed that the StringHttpMessageConverter by default adds the HTTP header Content-Type: text/plain rather than your desired text/html - configuring that correctly (in the way you configured the Jaxb2RootElementHttpMessageConverter in your question) might fix it
  • john
    john over 9 years
    @artbristol I also have similar question here on RestTemplate. If possible, can you help me out? I am stuck on that for a while and not able to understand how to make it work. Any help will be greatly appreciated.