restTemplate удалить с телом

Я пытаюсь выполнить DELETE с телом запроса, но продолжаю получать ошибку 400 (неверный запрос). Когда я делаю это в чванстве/почтальоне, он успешно удаляет запись. Но из кода Java я не могу этого сделать

Внешний API разработан таким образом, что ему требуется тело вместе с URL-адресом. Его нельзя изменить. пожалуйста, дайте мне знать, как я могу удалить эту запись с телом запроса

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;
        }
    }

когда дело доходит до исключения, я получаю запрос JSON в формате JSON, и то же самое отлично работает в Swagger/postman

Я немного погуглил и обнаружил, что у restTemplate есть проблема с удалением, когда есть тело запроса. эта статья не помогла https://jira.spring.io/browse/SPR-12361 есть ли способ заставить это работать


person Shiva    schedule 27.04.2016    source источник
comment
У вас уже есть тело запроса в requestEntity. Проверьте свой API и посмотрите, что он ожидает. Затем проверьте, сериализовано ли ваше тело так, как вы ожидали.   -  person Sotirios Delimanolis    schedule 27.04.2016
comment
тело запроса такое же. одно и то же тело работает для POST и PUT. Удаление работало нормально из пользовательского интерфейса swagger с теми же значениями, но не работает в коде Java.   -  person Shiva    schedule 27.04.2016
comment
Здесь недостаточно подробностей, чтобы мы могли вам помочь. Покажите нам, что отправляется по сети для Swagger. Покажите нам, что отправляется для примераRestTemplate. В этот момент вы, вероятно, сами найдете ответ.   -  person Sotirios Delimanolis    schedule 27.04.2016
comment
Я сделал CustomObjectMapper mapper = new CustomObjectMapper(); и отладка mapper.writeValueAsString(person) и тот же запрос, зарегистрированный кодом Java, отлично работает в пользовательском интерфейсе Swagger. Интересно, в чем будет проблема   -  person Shiva    schedule 27.04.2016
comment
Ошибка, на которую вы ссылаетесь, довольно очевидна. Spring на Java ‹ 1.8 не сможет отправить тело с помощью DELETE. Проблема на самом деле в java, а не в Spring. Я подозреваю, что это происходит из-за довольно строгого прочтения спецификации http, несмотря на то, что нет никакого способа заставить его работать, кроме как перейти на jdk 1.8 из-за ошибки.   -  person Taylor    schedule 28.04.2016


Ответы (2)


Другой способ исправить это — использовать restTemplate.exchange, вот пример:

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 */
}

Прелесть этого решения в том, что его можно использовать со всеми типами HttpMethod.

person Jim Holland    schedule 10.08.2018

Проблема существует для Spring версии 4.0.x или более ранней.
В более поздних версиях она была исправлена.

Это может быть поздний ответ, но в одном из моих проектов я решил эту проблему с помощью пользовательского ClientHttpRequestFactory до RestTemplate

Если для RestTemplate не указана фабрика, используется реализация по умолчанию SimpleClientHttpRequestFactory

В классе SimpleClientHttpRequestFactory метод DELETE не разрешен с телом запроса.

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

Просто напишите свою собственную реализацию как

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);
        }
    }
}

После этого создайте свой объект RestTemplate как

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

Исправление в более поздних версиях (4.1.x или выше) класса SimpleClientHttpRequestFactory

if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) ||
            "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) {
    connection.setDoOutput(true);
}
else {
    connection.setDoOutput(false);
}
person Pratapi Hemant Patel    schedule 06.06.2018