POST request via RestTemplate in JSON
Asked Answered
D

15

144

I didn't find any example how to solve my problem, so I want to ask you for help. I can't simply send POST request using RestTemplate object in JSON

Every time I get:

org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type

I use RestTemplate in this way:

...
restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);

What is my fault?

Doble answered 2/11, 2010 at 8:29 Comment(5)
@troyfolger the url is no longer validDevout
Thanks - this link is working as of this writing: spring.io/guides/gs/consuming-restDiley
To address the specific OP issue, above, you are probably missing an HTTP header with appropriate content type, see the answer from morganw09dev below.Diley
These issues are mostly related to the Server API configuration. You test the Server API using a Standalone client (like Postman ) and replicate the same headers in your request. At least in my case that did the Trick.Orel
@Johnny B, if this has been answered please mark the answerSpillway
R
179

This technique worked for me:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
            
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.put(url, entity);
Rattoon answered 25/5, 2011 at 17:24 Comment(7)
please explain which row should return result of http requestParham
For me it was not necessary to specify any headers. I have used the HttpEntity that takes a single parameter.Manzanilla
method .put() is void!Teat
Using postForEntity(url, entity, String.class) works in place of put(url, entity)Kinesthesia
In my case, put method throws Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 405 HTTP method PUT is not supported by this URL Azote
@Kanu, requestJson is valid JSON String or something else?Pious
Make sure you use org.springframework.http.HttpHeaders and not java.net.http.HttpHeadersToastmaster
N
116

I ran across this problem when attempting to debug a REST endpoint. Here is a basic example using Spring's RestTemplate class to make a POST request that I used. It took me quite a bit of a long time to piece together code from different places to get a working version.

RestTemplate restTemplate = new RestTemplate();

String url = "endpoint url";
String requestJson = "{\"queriedQuestion\":\"Is there pain in your hand?\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

The particular JSON parser my rest endpoint was using needed double quotes around field names so that's why I've escaped the double quotes in my requestJson String.

Nothing answered 3/6, 2015 at 14:51 Comment(4)
can u please help me on this #42241427Katheykathi
Can Spring use the message converters to automatically convert the Java Object to json like it did in Restful API with RestTemplate?Elman
Setting media type to APPLICATION_JSON is the key to resolve the problem.Appendicular
I resolved my problem using HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers); this lineSkelton
S
102

I've been using rest template with JSONObjects as follow:

// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);

// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(request.toString(), headers);

// send request and parse result
ResponseEntity<String> loginResponse = restTemplate
  .exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK) {
  JSONObject userJson = new JSONObject(loginResponse.getBody());
} else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED) {
  // nono... bad credentials
}
Strongbox answered 24/11, 2014 at 13:54 Comment(8)
Thanks - the JSONObject toString method was useful for me, it helped me get my JSONString accurate.Cart
How to developed above code for this : curl -vvv -X POST "localhost:8080/SillyService_SRC/oauth/…" ?Schizothymia
@Mikael Lepistö How can i retrieve these parameters from json at server end??Lodestone
@Lodestone I don't understand what do you mean... this is server side code in the response. If you are thinking how to parse json response, it depends on framework that you are using.Declarer
@MikaelLepistö I mean how to parse json response in the other end including how to receive the response in java??You have posted only the code for one end(ie, server side).Lodestone
@Lodestone If you get request body containing JSON string from your choice of HTTP server you can convert it to JSONObject like this: JSONObject obj = new JSONObject(jsonString);, but pretty much every java web server framework has some better way to do it.Declarer
Can we let Spring convert the java object to json for us with message converters behind the screen like Rest APIs?Elman
@Elman I don't suppose Spring does that automatically, probably you need to configure some service for sending requests and write DTOs and use them if you want more automation. Maybe someone who know Spring better than me can have better answer...Declarer
V
14

As specified here I guess you need to add a messageConverter for MappingJacksonHttpMessageConverter

Voyageur answered 2/11, 2010 at 12:14 Comment(0)
P
14

I'm doing in this way and it works .

HttpHeaders headers = createHttpHeaders(map);
public HttpHeaders createHttpHeaders(Map<String, String> map)
{   
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    for (Entry<String, String> entry : map.entrySet()) {
        headers.add(entry.getKey(),entry.getValue());
    }
    return headers;
}

// Pass headers here

 String requestJson = "{ // Construct your JSON here }";
logger.info("Request JSON ="+requestJson);
HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
logger.info("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
logger.info("Response ="+response.getBody());

Hope this helps

Preemption answered 21/11, 2017 at 11:29 Comment(0)
K
10

If you are using Spring 3.0, an easy way to avoid the org.springframework.web.client.HttpClientErrorException: 415 Unsupported Media Type exception, is to include the jackson jar files in your classpath, and use mvc:annotation-driven config element. As specified here.

I was pulling my hair out trying to figure out why the mvc-ajax app worked without any special config for the MappingJacksonHttpMessageConverter. If you read the article I linked above closely:

Underneath the covers, Spring MVC delegates to a HttpMessageConverter to perform the serialization. In this case, Spring MVC invokes a MappingJacksonHttpMessageConverter built on the Jackson JSON processor. This implementation is enabled automatically when you use the mvc:annotation-driven configuration element with Jackson present in your classpath.

Knotting answered 19/5, 2011 at 17:45 Comment(0)
L
7

The "415 Unsupported Media Type" error is telling you that the server will not accept your POST request. Your request is absolutely fine, it's the server that's mis-configured.

MappingJacksonHttpMessageConverter will automatically set the request content-type header to application/json, and my guess is that your server is rejecting that. You haven't told us anything about your server setup, though, so I can't really advise you on that.

Lenlena answered 2/11, 2010 at 8:47 Comment(0)
F
6

Why work harder than you have to? postForEntity accepts a simple Map object as input. The following works fine for me while writing tests for a given REST endpoint in Spring. I believe it's the simplest possible way of making a JSON POST request in Spring:

@Test
public void shouldLoginSuccessfully() {
  // 'restTemplate' below has been @Autowired prior to this
  Map map = new HashMap<String, String>();
  map.put("username", "bob123");
  map.put("password", "myP@ssw0rd");
  ResponseEntity<Void> resp = restTemplate.postForEntity(
      "http://localhost:8000/login",
      map,
      Void.class);
  assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
}
Feune answered 16/5, 2019 at 14:46 Comment(1)
This is really far down, but it worked for me. Not sure if there are any drawbacks, but it seems to be by far the simplest approach.Aryanize
H
5

This code is working for me;

RestTemplate restTemplate = new RestTemplate();
Payment payment = new Payment("Aa4bhs");
MultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("payment", payment);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headerObject);

Payment res = restTemplate.postForObject(url, httpEntity, Payment.class);
Horseshoe answered 20/10, 2016 at 11:10 Comment(3)
i am using a very similar approach and it did NOT work for me. for some reason my equivalent of your 'map' is not being converted to json or included as outbound body i.e., the target service does NOT see any payload.Stuyvesant
yep, this solution as shown will post in application/x-www-form-urlencoded format.Aret
I could not use a JSON string for payload my parser would not allow it (Jackson). I had to use a Java Map type object like above to solve my problem.Amery
C
4

I was getting this problem and I'm using Spring's RestTemplate on the client and Spring Web on the server. Both APIs have very poor error reporting, making them extremely difficult to develop with.

After many hours of trying all sorts of experiments I figured out that the issue was being caused by passing in a null reference for the POST body instead of the expected List. I presume that RestTemplate cannot determine the content-type from a null object, but doesn't complain about it. After adding the correct headers, I started getting a different server-side exception in Spring before entering my service method.

The fix was to pass in an empty List from the client instead of null. No headers are required since the default content-type is used for non-null objects.

Coulter answered 6/10, 2015 at 15:2 Comment(0)
S
3

If you dont want to process response

private RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(serviceURL, request, Void.class);

If you need response to process

String result = restTemplate.postForObject(url, entity, String.class);
Singleaction answered 12/12, 2018 at 12:26 Comment(0)
S
2

I tried as following in spring boot:

ParameterizedTypeReference<Map<String, Object>> typeRef = new ParameterizedTypeReference<Map<String, Object>>() {};
public Map<String, Object> processResponse(String urlendpoint)
{
    try{
    
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //reqobj
        JSONObject request = new JSONObject();
        request.put("username", name);
        //Or Hashmap 
        Map<String, Object> reqbody =  new HashMap<>();
        reqbody.put("username",username);
        Gson gson = new Gson();//mvn plugin to convert map to String
        HttpEntity<String> entity = new HttpEntity<>( gson.toJson(reqbody), headers);
        ResponseEntity<Map<String, Object>> response = resttemplate.exchange(urlendpoint, HttpMethod.POST, entity, typeRef);//example of post req with json as request payload
        if(Integer.parseInt(response.getStatusCode().toString()) == HttpURLConnection.HTTP_OK)
        {
            Map<String, Object>  responsedetails = response.getBody();
            System.out.println(responsedetails);//whole json response as map object
            return responsedetails;
        }
    } catch (Exception e) {
        // TODO: handle exception
        System.err.println(e);
    }
    return null;
}
Smyth answered 8/7, 2020 at 12:46 Comment(0)
C
1

If you don't want to map the JSON by yourself, you can do it as follows:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<String> result = restTemplate.postForEntity(uri, yourObject, String.class);
Cryptic answered 7/5, 2020 at 18:14 Comment(0)
C
0

For me error occurred with this setup:

AndroidAnnotations Spring Android RestTemplate Module and ...

GsonHttpMessageConverter

Android annotations has some problems with this converted to generate POST request without parameter. Simply parameter new Object() solved it for me.

Conchiferous answered 5/5, 2015 at 10:17 Comment(0)
P
0

You can make request as a JSON object

JSONObject request = new JSONObject();
request.put("name","abc"); 
ResponseEntity<JSONObject> response =restTemplate.postForEntity(append_url,request,JSONObject.class);                                                          `enter code here`
Prolusion answered 4/10, 2021 at 6:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.