Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to send MultiValueMap containing a file in a POST request to Spring rest web service?

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]]]
like image 418
Sami Avatar asked Sep 14 '25 22:09

Sami


1 Answers

I spend so much time on this error!

FormHttpMessageConverter has 3 converters for parts:

  1. ByteArrayHttpMessageConverter - writes byte[].class
  2. StringHttpMessageConverter - String.class
  3. 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

like image 59
ivanka Avatar answered Sep 17 '25 12:09

ivanka