Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to POST XML using RestTemplate

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 ?

like image 204
zfranciscus Avatar asked Mar 11 '13 07:03

zfranciscus


1 Answers

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).

like image 198
artbristol Avatar answered Oct 04 '22 22:10

artbristol