415 Unsupported Media Type while sending json file over REST Template

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


415 Unsupported Media Type while sending json file over REST Template



I am trying to send a json file over REST Template. When I send it via POST man as MULTIPART_FORM_DATA, it works fine. The name I am supposed to give is specific (lets say aaa). Attached screenshot screenshot of POSTMAN. But when I try same in code as specified in another stackoverflow post, I get 415 Unsupported Media Type error as


org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE]
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:616) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:572) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:532) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE]
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:332) ~[spring-web-4.1.9.RELEASE.jar:4.1.9.RELEASE]
at



Please do not mark it as duplicate as the specified answer did not work for me. Not sharing code as my code is exactly same as this except


requestParamerterMap.add("attachment", resource);



where as my code is


requestParamerterMap.add("aaa", resource);



After debugging it from the server side, looks like request is reaching out to server. I was able to see below error in the server side:


[{error=Unsupported Media Type, exception=org.springframework.web.HttpMediaTypeNotSupportedException, message=Content type 'application/octet-stream' not supported, status=415, timestamp=1532557180124}] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@74d4827a]



So, from the server side logs, I am not sure where the content type is getting added as application/octet-stream as I have set the content type as


headers.setContentType(MediaType.MULTIPART_FORM_DATA);



Below is the code from server controller. Server side code uses Spring boot.


@RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,consumes = {"multipart/form-data"})
@ResponseBody
public MyResponse uploadPhoto(@RequestPart(value = "aaa", required = false) Optional<MyRequest> myRequest,
@RequestPart(value = "file", required = false) Optional<MultipartFile> file,
HttpServletRequest request) {
//some logic
return myResponse;
}



The server code has an interceptor where I can see my request has content type as multipart/form-data. It does not reach to RestController



When I debugged the server side code in 2 cases:



enter image description here



enter image description here



One thing I figured out that file iteam has content type as application/json when I post from POSTMAN and the content type was application/octet-stream when the request goes from client side code.



In my client side code, I am creating JSONObject as


JSONObject json = new JSONObject();
json.append("myKey", "myValue");



and convert it to byte array as


json.toString().getBytes("UTF-8")



then I have followed this . The difference in my code is, I am sending my JSONObject as byte stream as I can not create file (performance issues).



And I cant not send JSONObject as string as server is expecting multipart-form-data for both file and aaa



I have created the restTemplate as


public RestTemplate myRestTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setReadTimeout(HTTP_CLIENT_TIMEOUT);
requestFactory.setConnectTimeout(HTTP_CLIENT_TIMEOUT);

RestTemplate restTemplate = new RestTemplate(requestFactory);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
restTemplate.setMessageConverters(messageConverters);
return restTemplate;



Here is the client side code which calls the service:


public Optional<JSONObject> callService(byte multipartFile) {
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
InputStream stream = new ByteArrayInputStream(multipartFile);
MultipartByteArrayResource resource = new MultipartByteArrayResource(multipartFile,fileName);


body.add("aaa", resource);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

try {
response = restTemplate.postForObject(url, requestEntity , String.class);


} catch (Exception exception) {
LOG.error("Error", exception);
return Optional.empty();
}
}

public class MultipartInputStreamFileResource extends InputStreamResource {

private final String filename;

MultipartInputStreamFileResource(InputStream inputStream, String filename) {
super(inputStream);
this.filename = filename;
}

@Override
public String getFilename() {
return this.filename;
}

@Override
public long contentLength() throws IOException {
return -1; // we do not want to generally read the whole stream into memory ...
}
}



And same code works when I send file (note file and aaa are two different things though both are multipart/form-data in server side. file is just a file of any time (image/text/pdf) but aaa is json data file)



After debugging little bit more, what I observed is server side controller is expecting the file content to be json as Jackson try to deserialize that json to MyRequest object. When I send post from POSTMAN, it has the json content so working as expected but from the client side code, the content is byteArray, and its not getting deserialize to MyRequest object. Not sure how to fix this





What is the media type that the server's controller method accepts? Can you post the server controller annotations? (Assuming you're using Spring). Looking at the message, the server endpoint might only accept application/json.
– Benjamin Liu
yesterday







server controller accepts multipart/form-data. Updating the Question with server code
– user123475
yesterday





Can I actually see the entire client code that you've written as well? Just making sure you actually are using a converter that will perform the serialization. It seems like if you don't write the converter it will be left as octet-stream.
– Benjamin Liu
yesterday





Maybe you could try emulating what POSTMAN is doing and sending the request with content-type application/json just to test.
– Benjamin Liu
yesterday




1 Answer
1



The server-side exception is produced by org.springframework.http.converter.json.MappingJackson2HttpMessageConverter. Jackson is a JSON library and MessageConverter are used by Spring to format requests and responses.


org.springframework.http.converter.json.MappingJackson2HttpMessageConverter



Can it be that the client sends an "Accept: application/octet-stream" while the server has a @Produces(APPLICATION_JSON) annotation? That would mean that the server processes the request and only has problems sending the response. You could add some log.info() statements in the server to verify this.





No. Request is not even reaching to server's Rest Controller. It reaches the interceptor in server side and fails while deserializing at RestController's method. Sample code is attached from server side too
– user123475
yesterday






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Keycloak server returning user_not_found error when user is already imported with LDAP

PHP parse/syntax errors; and how to solve them?

How to scale/resize CVPixelBufferRef in objective C, iOS