27

I'm having a problem using Spring restTemplate.

For now i'm sending a PUT request for a restful service and that restful service send me back important informations in response.

The question is that restTemplate.put are a void method and not a string so i can't see that response.

Following some answers i've change my method and now i'm using restTemplate.exchange, here are my method:

public String confirmAppointment(String clientMail, String appId)
{
    String myJsonString = doLogin();

    Response r = new Gson().fromJson(myJsonString, Response.class);

    // MultiValueMap<String, String> map;
    // map = new LinkedMultiValueMap<String, String>();

    // JSONObject json;
    // json = new JSONObject();

    // json.put("status","1");

    // map.add("data",json.toString());

    String url = getApiUrl() + "company/" + getCompanyId() + "/appointment/" + appId + "?session_token=" + r.data.session_token;
    String jsonp = "{\"data\":[{\"status\":\"1\"}]}";

    RestTemplate rest = new RestTemplate();

    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json");
    headers.add("Accept", "*/*");

    HttpEntity<String> requestEntity = new HttpEntity<String>(jsonp, headers);
    ResponseEntity<String> responseEntity = 
            rest.exchange(url, HttpMethod.PUT, requestEntity, String.class);

    return responseEntity.getBody().toString();
}

Using the method above, i receive a 400 Bad Request

I know my parameters, url and so, are just fine, cause i can do a restTemplate.put request like this:

try {
    restTemplate.put(getApiUrl() + "company/" + getCompanyId() + "/appointment/" + appId + "?session_token=" + r.data.session_token, map);
} catch(RestClientException j)
{
    return j.toString();
}

The problem (like i said before) is that the try/catch above does not return any response but it gives me a 200 response.

So now i ask, what can be wrong?

Alexandre
  • 751
  • 2
  • 11
  • 27
  • Use the `execute` methods: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/client/RestTemplate.html – Sotirios Delimanolis Jun 03 '13 at 14:34
  • 2
    @Alexandre : Conventionally HTTP PUT is used for the operations which the user is aware. For an example, to Update something we can use HTTP PUT, there it is not intended to return a response body. May be status code or status message you can send. For that you can use headers to get it done. If you are expecting a response body that means you should deviate from HTTP PUT to HTTP POST. There you will be able to read the response in proper manner. – MCF Jun 03 '13 at 14:53
  • @MCF, unfortunately the restful service i'm accessing requires a PUT to update information's about a object and return information's about the update. If i send a POST request, the restful service return error. – Alexandre Jun 03 '13 at 15:13
  • @SotiriosDelimanolis, can you show me a example of usage? Sorry, my english are not so good and i'm new to restTemplate and Java :( – Alexandre Jun 03 '13 at 15:18
  • @Alexandre See an example here: http://stackoverflow.com/questions/15107494/resttemplate-usage – Sotirios Delimanolis Jun 03 '13 at 15:20
  • @SotiriosDelimanolis, i don't understand, your link shows a `exchange` example, not a `execute`. – Alexandre Jun 03 '13 at 20:08
  • @Alexandre Please read the javadoc in my first comment. The methods are different, but the end result is much the same. Use either. – Sotirios Delimanolis Jun 03 '13 at 20:10
  • Sorry @SotiriosDelimanolis, as i said before, i do not understand Spring well yet and i didnt understand how the `execute` method works. I've edited my question by using the `exchange` method. With more accurate informations about my structure. I'll be thankful if you can solve this problem. Thanks in advance bro :) – Alexandre Jun 03 '13 at 20:35
  • @Alexandre I'm pretty sure it's because of `String jsonp = map.toString();`. `jsonp` will not be valid json because of missing quotation marks (try to `println()` it before you call the method). Bad json, means the content-type is invalid and therefore your request is bad, ie. 400 error. – Sotirios Delimanolis Jun 03 '13 at 20:44
  • @SotiriosDelimanolis, ok, i edited the question with the modifications but still get 400 BAD REQUEST – Alexandre Jun 03 '13 at 20:50
  • @Alexandre The `=` should be `:` in the json string. Always make sure to validate your json with services like [JSONLint](http://jsonlint.com/) – Sotirios Delimanolis Jun 03 '13 at 20:54
  • @SotiriosDelimanolis, ok, i put the `:` and the validation are fine. But i still get a `400 BAD REQUEST`... :( – Alexandre Jun 03 '13 at 20:58
  • @Alexandre Then your headers are incorrect. – Sotirios Delimanolis Jun 03 '13 at 20:59

4 Answers4

37

Here's how you can check the response to a PUT. You have to use template.exchange(...) to have full control / inspection of the request/response.

    String url = "http://localhost:9000/identities/{id}";       
    Long id = 2l;
    String requestBody = "{\"status\":\"testStatus2\"}";
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON); 
    HttpEntity<String> entity = new HttpEntity<String>(requestBody, headers); 
    ResponseEntity<String> response = template.exchange(url, HttpMethod.PUT, entity, String.class, id);
    // check the response, e.g. Location header,  Status, and body
    response.getHeaders().getLocation();
    response.getStatusCode();
    String responseBody = response.getBody();
dan carter
  • 4,158
  • 1
  • 33
  • 34
  • Your example on using HttpHeaders solved this issue for me. I was using StringEntity instead of HttpHeaders and was getting 400 errors that way. – Zack Macomber Feb 16 '16 at 13:52
10

You can use the Header to send something in brief to your clients. Or else you can use the following approach as well.

restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, ...)

You will be able to get a Response Entity returned through that.

MCF
  • 768
  • 2
  • 6
  • 21
  • I still don't understand what you mean by _can use the Header to send something in brief to your clients_. – Sotirios Delimanolis Jun 03 '13 at 14:42
  • @SotiriosDelimanolis I have seen an apporach where the Headers to send some very brief information via HTTP.PUT. The clients need to read the headers and retrieve it. – MCF Jun 03 '13 at 14:43
  • Let's say that you want to communicate the clients that the operation which was done through HTTP.PUT was unsuccessful. In that case from server side we can set an additional header parameter to communicate that incident. Therefore, the people who requested for HTTP.PUT will be aware by reading the header at least. – MCF Jun 03 '13 at 14:44
  • Ok, so you want to use HTTP headers. That doesn't answer his question of getting the HTTP PUT response. The other part of your answer does. – Sotirios Delimanolis Jun 03 '13 at 14:44
0

Had the same issue. And almost went nuts over it. Checked it in wireshark: The problem seems to be the escape characters from the request body:

String jsonp = "{\"data\":[{\"status\":\"1\"}]}";

The escape character (backslash) is not resolved. The String is sent with the backslashes, which is obviously not a valid json and therefore no valid request(-body).

I bypassed this by feeding everything in with an Object, that is mapping all the properties.

Guest
  • 1
0

You can use the httpEntityCallback() and responseEntityExtractor() from RestTemplate to construct your own put method:

ResponseEntity<MyJsonResponse> response = restTemplate.execute(url,
    HttpMethod.PUT,
    restTemplate.httpEntityCallback(myJsonAsJavaObject),
    restTemplate.responseEntityExtractor( MyJsonResponse.class)
);