restTemplate delete with body

16,448

Solution 1

Another way to fix this is to use restTemplate.exchange, here's an example:

try {
      String jsonPayload  = GSON.toJson(request);
      HttpEntity<String> entity = new HttpEntity<String>(jsonPayload.toString(),headers());
      ResponseEntity resp = restTemplate.exchange(url, HttpMethod.DELETE, entity, String.class);
} catch (HttpClientErrorException e) {
      /* Handle error */
}

The nice thing about this solution is that you can use it with all HttpMethod types.

Solution 2

Issue exists for Spring version 4.0.x or earlier.
In later version it has been fixed.

This might be a late answer, but in one of my project I solved this issue via a custom ClientHttpRequestFactory to RestTemplate

If no factory is provided to RestTemplate, it uses default implementation SimpleClientHttpRequestFactory

In SimpleClientHttpRequestFactory class, DELETE method is not allowed with request body.

if ("PUT".equals(httpMethod) || "POST".equals(httpMethod) ||     
         "PATCH".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}

Just write your own implementation as

import java.io.IOException;
import java.net.HttpURLConnection;

import org.springframework.http.client.SimpleClientHttpRequestFactory;

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory {

    @Override
    protected void prepareConnection(HttpURLConnection connection, 
            String httpMethod) throws IOException {

        super.prepareConnection(connection, httpMethod);
        if("DELETE".equals(httpMethod)) {
            connection.setDoOutput(true);
        }
    }
}

After that create your RestTemplate object as

RestTemplate template = new RestTemplate(
                            new CustomClientHttpRequestFactory());

Fix in later versions of (4.1.x or above) SimpleClientHttpRequestFactory class

if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) ||
            "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}
Share:
16,448

Related videos on Youtube

Shiva
Author by

Shiva

Updated on June 18, 2022

Comments

  • Shiva
    Shiva almost 2 years

    I am trying to do DELETE with request body but I keep getting 400 (bad request) error. When I do it in the swagger/postman, it is successfully deleting the record. But from the Java code I can't do that

    The external API is designed in a way that it needs body along with URL. It can't be changed. please let me know how can I delete that entry with request body

    public Person delete(Person person, String url, Map<String, String> uriVariables) throws JsonProcessingException {
            RestTemplate restTemplate = new RestTemplate();
            CustomObjectMapper mapper = new CustomObjectMapper();
            HttpEntity<Person> requestEntity = new HttpEntity<Person>(person);
            try {
                ResponseEntity<Person> responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Person.class, uriVariables);
                return responseEntity.getBody();
            } catch (RestClientException e) {
                System.out.println(mapper.writeValueAsString(person));
                throw e;
            }
        }
    

    when it goes to exception, I will get the JSON request in JSON format and the same works fine in Swagger/postman

    I did some googling and found that restTemplate have problem deleting when there is request body. this article wasn't helpful https://jira.spring.io/browse/SPR-12361 is there any way to get it work

    • Taylor
      Taylor
      The bug you linked to is fairly self-explanatory. Spring on java <1.8 will not be able to send a body with a DELETE. The issue is actually in java, not Spring. I suspect this comes from a rather strict reading of the http spec, regardless, there's no way to get it to work short of moving to jdk 1.8, per the bug.