Тело ResponseEntity потеряно между двумя вызовами веб-сервиса

#java #spring #spring-boot #spring-cloud-feign

#java #spring #весенняя загрузка #spring-cloud-feign

Вопрос:

У меня есть веб-сервис, который вызывает другой WS и возвращает ответ от второго WS. Это выглядит так:

 // MyController
public ResponseEntity<Foo> requestFooController(@RequestBody @Valid Bar request) {
     return this.myService.requestFooService(request);
}

//MyService
ResponseEntity<Foo> requestFooService(Bar request) {
  Buzz improvedRequest = ...
  return this.secondWS.secondRequestFoo(improvedRequest);
}
  

Когда я вызываю API через Postman, я получаю HTTP OK-ответ с пустым телом. Тем не менее, когда я нахожусь в режиме отладки, я вижу, что служба возвращает ResponseEntity с телом. Заголовки, однако, не потеряны.

Я изменил свой код вот так, и он работает нормально:

 // MyController
public ResponseEntity<Foo> requestFooController(@RequestBody @Valid Bar request) {
     ResponseEntity<Foo> tmp = this.myService.requestFooService(request);
     return ResponseEntity.status(tmp.getStatusCode()).body(tmp.getBody());
}
  

Теперь через Postman у меня есть ожидаемое тело. Однако я не понимаю поведение. Я подумал, что, возможно, это связано с тем, что тело представляет собой какой-то поток, который можно прочитать один раз или что-то подобное. Но, прочитав исходный код, я не вижу ничего, что могло бы объяснить такое поведение.

Я использую Netflix-stack (поэтому HTTP-вызовы между двумя WS выполняются через Feign клиент).

Есть идеи, почему я получаю этот результат?

РЕДАКТИРОВАТЬ: Более подробная информация о моей задаче: SpringBoot 1.5.3.RELEASE Feign 2.0.5

Комментарии:

1. Какие версии spring-boot вы используете? Существует ошибка, зависящая от конкретной версии, которая привела к потере имени составного тела, а затем не соответствует параметрам. Вы используете feign, но используете ли вы eureka и zuul в своем стеке Netflix?

2. Да, я использую Zuul и Eureka. Я мог бы попытаться обойти zuul и посмотреть, что произойдет.

Ответ №1:

Существует ошибка, которая приводит к сбою именованного тела составного сообщения HTTP. Признаком этого является то, что вы делаете запрос POST с телом, а Spring-Boot не может сопоставить его с конечной точкой. Исключение, которое я вижу, это:

 2019-01-23 15:22:45.046 DEBUG 1639 --- [io-8080-exec-10] .w.s.m.m.a.ServletInvocableHandlerMethod : Failed to resolve argument 3 of type 'org.springframework.web.multipart.MultipartFile'
    org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
  

Zuul выполняет кэширование запроса, чтобы повторить попытку несколько раз. В этом процессе не удается сохранить именованное поле для двоичного тела. Возможно, это сработает, если вы предварите запрос zuul. Поэтому вместо http://myserver.com/myservice/endpoint используйте zuul в пути:http://myserver.com/zuul/myservice/endpoint

Это позволит эффективно избежать сохранения запроса и механизма повторных попыток.

Более подробная информация доступна по этой проблеме в списке ошибок Zuul на GitHub.

Комментарии:

1. Я обновляю до spring-boot 2.1.3, чтобы решить эту проблему в рабочей среде.

2. Спасибо за информацию! Я проверю, есть ли у меня аналогичная проблема в журнале отладки. Я думаю, это будет еще одним аргументом для ускорения обновления 🙂