how to send MultiValueMap containing a file in a POST request to Spring rest web service?
java, post, rest, spring
Solution
I spend so much time on this error!
FormHttpMessageConverter has 3 converters for parts:
- ByteArrayHttpMessageConverter - writes byte[].class
- StringHttpMessageConverter - String.class
- ResourceHttpMessageConverter - org.springframework.core.io.Resource.class - here is the trick
Instead of putting file itself, you should put it as Resource:
File file = new File("some_path");
Resource resource = new FileSystemResource(file);
map.add("file", resource);
FileSystemResource is from package org.springframework.core.io
Problem
I want to send a POST request which includes a file and another custom object using restTemplate. I have tried the code below, but didn't get it working as it is missing an `HtttpMessageConverter` for `java.io.File` Is MultiValueMap the right choice to send both objects in one request? If not, any suggestions? If yes, then how do I get the message converter problem solved? The client (adopted from here and here): ``` RestTemplate rest = new RestTemplate(); HttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); HttpMessageConverter stringHttpMessageConverternew = new StringHttpMessageConverter(); List<HttpMessageConverter<?>> conv = new ArrayList<HttpMessageConverter<?>> (); conv.add(formHttpMessageConverter); conv.add(stringHttpMessageConverternew); rest.setMessageConverters(conv); MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>(); File f = new File("testFile.txt"); map.add("file", f); NewObject a = new NewObject("123", "xxx", "xxx", "blahblah", "5432"); map.add("newObject", a); String result = rest.postForObject("http://localhost:8080/test/upload", map, String.class); System.out.println(result); ``` The controller: ``` @RequestMapping(value="/upload", method=RequestMethod.POST) public @ResponseBody String uploadArtefact(@RequestBody MultiValueMap<String, Object> o) { logger.info("tesssting: " + o); File x = (File) o.get("file").get(0); logger.info("File name " + x.getName()); NewObject a = (NewObject) o.get("newObject").get(0); logger.info("New Object: " + a); return "finished"; } ``` This is the error that I am getting on the client side: ``` Exception in thread "main" org.springframework.http.converter.HttpMessageNotWritableException: Could not write request: no suitable HttpMessageConverter found for request type [java.io.File] at org.springframework.http.converter.FormHttpMessageConverter.writePart(FormHttpMessageConverter.java:317) at org.springframework.http.converter.FormHttpMessageConverter.writeParts(FormHttpMessageConverter.java:275) at org.springframework.http.converter.FormHttpMessageConverter.writeMultipart(FormHttpMessageConverter.java:264) at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:204) at org.springframework.http.converter.FormHttpMessageConverter.write(FormHttpMessageConverter.java:72) at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:751) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:540) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:503) at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:331) at uk.ac.ncl.rest.Test.main(Test.java:47) ``` and these two lines are logged on the server side: ``` 2015-02-24 16:44:14.772 WARN 38776 --- [nio-8080-exec-1] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate deserialization for type [map type; class org.springframework.util.MultiValueMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.Object]]]: com.fasterxml.jackson.databind.JsonMappingException: Can not find a deserializer for non-concrete Map type [map type; class org.springframework.util.MultiValueMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.Object]]] 2015-02-24 16:44:14.772 WARN 38776 --- [nio-8080-exec-1] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate deserialization for type [map type; class org.springframework.util.MultiValueMap, [simple type, class java.lang.Object] -> [collection type; class java.util.List, contains [simple type, class java.lang.Object]]]: com.fasterxml.jackson.databind.JsonMappingException: Can not find a deserializer for non-concrete Map type [map type; class org.springframework.util.MultiValueMap, [simple type, class java.lang.Object] -> [collection type; class java.util.List, contains [simple type, class java.lang.Object]]] ```