2016-03-30 5 views
2

Я только начинаю с Akka HTTP, и у меня возникают проблемы с маршрутизацией DSL и маршалингом. Тильда в результатах установки «маршрут» в ошибке:Akka HTTP Routing and Marshaling

value ~ is not a member of akka.http.scaladsl.server.RequestContext ⇒ scala.concurrent.Future[akka.http.scaladsl.server.RouteResult] possible cause: maybe a semicolon is missing before 'value ~'?

Кроме того, маршалингом JSON в пункте «получить» вызывает ошибку:

◾Cannot find JsonWriter or JsonFormat type class for scala.collection.immutable.Map[String,scala.collection.mutable.Map[String,Tweet]]

◾not enough arguments for method toJson: (implicit writer: spray.json.JsonWriter[scala.collection.immutable.Map[String,scala.collection> .mutable.Map[String,Tweet]]])spray.json.JsValue. Unspecified value parameter writer.

Я следовал примеры документации довольно поэтому я был бы признателен за помощь в понимании этих ошибок и их решении. Благодарю.

API

import akka.actor.ActorSystem 
import scala.concurrent.Future 
import akka.stream.ActorMaterializer 
import akka.http.scaladsl.Http 
import akka.http.scaladsl.server.Directives.path 
import akka.http.scaladsl.server.Directives.pathPrefix 
import akka.http.scaladsl.server.Directives.post 
import akka.http.scaladsl.server.Directives.get 
import akka.http.scaladsl.server.Directives.complete 
import akka.http.scaladsl.unmarshalling.Unmarshal 
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ 
import akka.http.scaladsl.server.Directives.{entity, as} 
import akka.http.scaladsl.model.StatusCodes.{Created, OK} 
import spray.json._ 
import DefaultJsonProtocol._ 
import akka.stream.Materializer 
import scala.concurrent.ExecutionContext 

trait RestApi { 
    import TweetProtocol._ 
    import TweetDb._ 

    implicit val system: ActorSystem 
    implicit val materializer: Materializer 
    implicit val execCtx: ExecutionContext 

    val route = 
    pathPrefix("tweets") { 
     (post & entity(as[Tweet])) { tweet => 
     complete { 
      Created -> Map("id" -> TweetDb.save(tweet)).toJson 
     } 
     } ~ 
     (get) { 
     complete { 
      OK -> Map("tweets" -> TweetDb.find()).toJson 
     } 
     } 
    } 
} 

object TweetApi extends App with RestApi { 
    implicit val system = ActorSystem("webapi") 
    implicit val materializer = ActorMaterializer() 
    implicit val execCtx = system.dispatcher 

    val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) 

    println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") 
    Console.readLine() 

    bindingFuture.flatMap(_.unbind()).onComplete { _ => system.shutdown() } 
} 

Протокол

import spray.json.DefaultJsonProtocol 

case class Tweet(author: String, body: String) 

object TweetProtocol extends DefaultJsonProtocol { 
    implicit val TweetFormat = jsonFormat2(Tweet.apply) 
} 

Псевдо-база

import scala.collection.mutable.Map 

object TweetDb { 
    private var tweets = Map[String, Tweet]() 

    def save(tweet: Tweet) = { 
    val id: String = java.util.UUID.randomUUID().toString() 
    tweets += (id -> tweet) 
    id 
    } 

    def find() = tweets 

    def findById(id: String) = tweets.get(id) 
} 
+3

Вы можете исправить одну проблему, импортировав 'import akka.http.scaladsl.server.Directives._' вместо этих отдельных импортов из' Directives'. Я предполагаю, что там есть какие-то импликации, которые будут импортироваться, когда вы импортируете все, и это позволяет использовать оператор '~'. – cmbaxter

ответ

2

Для вашего 1-й ошибки, попробуйте су ggestion из комментария, т.е. импортировать все из директив

Для второй части

◾Cannot find JsonWriter or JsonFormat type class for scala.collection.immutable.Map[String,scala.collection.mutable.Map[String,Tweet]]

◾not enough arguments for method toJson: (implicit writer: spray.json.JsonWriter[scala.collection.immutable.Map[String,scala.collection> .mutable.Map[String,Tweet]]])spray.json.JsValue. Unspecified value parameter writer.

Вам необходимо определить JsonFormat для Map[String, mutable.Map[String, Tweet]]

Создавая объект на TweetProtocol, простираясь RootJsonFormat например.

type DBEntry = Map[String, mutable.Map[String, Tweet]] 
object TweetProtocol extends DefaultJsonProtocol { 
    implicit object DBEntryJsonFormat extends RootJsonFormat[DBEntry] { 
    override def read(json: JSValue) { 
     // your implementation 
    } 
    override def write(dbEntry: DBEntry) { 
     // implementation 
    } 
    } 
} 
+0

У меня была такая же ошибка: «значение ~ не является членом akka.http.scaladsl.server.Route». – Readren