Вариант результата в akka-http
У меня возникла проблема при попытке вернуть результат Option из aka-http.
По сути, это может быть 404.
pathPrefix("contacts" / Segment) { id =>
get {
contactService.getById(id).map {
case Some(c: ContactDto) => complete(OK -> toResource(c))
case None => complete(HttpResponse(NotFound))
}
}
}
Что дает мне и ошибку:
[error] found : scala.concurrent.Future[akka.http.scaladsl.server.StandardRoute]
[error] required: akka.http.scaladsl.server.Route
[error] (which expands to) akka.http.scaladsl.server.RequestContext => scala.concurrent.Future[akka.http.scaladsl.server.RouteResult]
[error] contactService.getById(id).map {
Любая помощь будет принята с благодарностью.
2 ответа
Проблема, которую вы видите здесь, связана с тем, что вы используете Future
а не из-за Option
, Я собираюсь предположить, что вызов contactService.getById(id)
возвращает Future
, В результате любой маршрут в вашем дереве маршрутизации должен быть Route
(Короче для RequestContext => Future[RouteResult]
) и ваш Future
само по себе не Route
, тогда вам нужно внести небольшое изменение, чтобы справиться с этой ситуацией. Вы должны быть в состоянии использовать onComplete
директива в сочетании с вашим Future
следующее:
pathPrefix("contacts" / Segment) { id =>
get {
val fut = contactService.getById(id)
onComplete(fut){
case util.Success(Some(c: ContactDto)) =>
complete(OK -> toResource(c))
case util.Success(None) =>
complete(HttpResponse(NotFound))
case util.Failure(ex) =>
complete(HttpResponse(InternalServerError))
}
}
}
Этот код теперь обрабатывает 3 возможных результата из Future
(успех с Some
Удачи с собой None
и провал), производя Route
для каждого из этих случаев. Это должно исправить вашу проблему.
Ответ @cmbaxter верный, но если вы довольны стандартными кодами состояния для трех вышеупомянутых случаев (Ok, NotFound, InternalServerError), то вы можете упростить код, чтобы он просто выполнялся напрямую с возвращаемой функцией Future[Option[T]]
,
pathPrefix("contacts" / Segment) { id =>
get {
complete(contactService.getById(id).map(toResource))
}
}
Это предполагает, что toResource
возвращает тип, где ToEntityMarshaller
существует для типа, возвращаемого этой функцией. Акка предоставляет оборудование для Future
а также Option
так что вам просто нужно поставить T
часть. Например, если вы возвращали JSON и использовали Spray-JSON, вы можете определить JsonWriter[T]
и последствия в akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
сделает все остальное Смотрите спрей-json-support.
map(toResource)
может на самом деле не требуется, но я предполагаю, что делает дополнительное преобразование ContactDto
к другому типу - если он просто конвертирует его в json или аналогичный, вы можете удалить его и использовать встроенную поддержку сортировки, как описано выше.