2017-11-01 6 views
1

私はscalaのplay framework 2.5でwebsocketを使用しようとしています。 今、複数のメッセージタイプを交換したいと思います。複数のメッセージタイプを持つプレーフレームワーク上のwebsocketのための俳優 - scala

しかし、クライアントがwebsocket経由でjsonを送信すると、次のエラーが発生します。

複数のメッセージタイプを交換するには、別の方法を選択する必要がありますか?

何かが見つからないか、それとも簡単な方法がありますか?

[error] a.a.OneForOneStrategy - {"sort":"post", "to":"receiver","message":"Test"} (of class play.api.libs.json.JsObject) 
scala.MatchError: {"sort":"post", "to":"receiver","message":"Test"} (of class play.api.libs.json.JsObject) 
     at controllers.MessageController$MessageActor$$anonfun$receive$1.applyOrElse(MessageController.scala:72) 
     at akka.actor.Actor$class.aroundReceive(Actor.scala:514) 
     at controllers.MessageController$MessageActor.aroundReceive(MessageController.scala:63) 
     at akka.actor.ActorCell.receiveMessage(ActorCell.scala:527) 
     at akka.actor.ActorCell.invoke(ActorCell.scala:496) 
     at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257) 
     at akka.dispatch.Mailbox.run(Mailbox.scala:224) 
     at akka.dispatch.Mailbox.exec(Mailbox.scala:234) 
     at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) 
     at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) 

models.scala

abstract class WSMessageIn() 

// Classes for input 
case class PostMessage(
    sort: String = "post", 
    to: String, 
    ... 
    message: Option[String] = None 
) extends WSMessageIn 

object PostMessage { 
    implicit val postMessageFormat = Json.format[PostMessage] 
} 

case class MessageFromIn(
    sort: String = "receive", 
    from: String, 
    ... 
    message: Option[String] = None 
) extends WSMessageIn 

object MessageFromIn { 
    implicit val messageFromInFormat = Json.format[MessageFromIn] 
} 

object WSMessageIn { 
    implicit def json2object(value: JsValue): WSMessageIn = { 
    (value \ "sort").as[String] match { 
     case "post" => value.as[PostMessage] 
     case "receive" => value.as[MessageFromIn] 
    } 
    } 

    implicit def object2json(in: WSMessageIn): JsValue = { 
    in match { 
     case in: PostMessage => Json.toJson(in) 
     case in: MessageFromIn => Json.toJson(in) 
    } 
    } 
} 

MessageController.scala

class MessageController @Inject() (
    silhouette: Silhouette[DefaultEnv], 
    .. 
    implicit val system: ActorSystem, 
    implicit val materializer: Materializer) 
    extends Controller { 

    class MessageActor(out: ActorRef) extends Actor { 

    override def receive = { 
     case message: JsValue => 
     message match { // !!The error occurs here 
      case message: PostMessage => 
      ... 
      case message: MessageFromIn => 
      ... 
     } 
    } 
    } 

    object MessageActor { 
    def props(out: ActorRef) = Props(new MessageActor(out)) 
    } 

    implicit val messageFlowTransformer = MessageFlowTransformer.jsonMessageFlowTransformer[JsValue, JsValue] 

    def socket() = WebSocket.acceptOrResult[JsValue, JsValue] { request => 
    implicit val req = Request(request, AnyContentAsEmpty) 
    silhouette.SecuredRequestHandler { securedRequest => 
     Future.successful(HandlerResult(Ok, Some(securedRequest.identity))) 
    }.map { 
     case HandlerResult(r, Some(user)) => Right(ActorFlow.actorRef(out => MessageActor.props(out))) 
     case HandlerResult(r, None) => Left(r) 
    } 
    } 
} 

答えて

0

あるとして:WebSocket.acceptOrResult[JsValue, JsValue]あなたのWebSocketはJsValueを受け取ることを期待しています。

これはMessageActorに以下のあなたのコードに合わせているようだ:

override def receive = { 
    case message: JsValue => // ... 
} 

しかし、あなたはJsValueからWSMessageInへの変換は、ユーザーの介入なしに起こることを期待すべきではありません。あなたは何ができるか

は単純です:あなたは、おそらく暗黙的な変換を期待していた

override def receive = { 
    case message: JsValue => 
    WSMessageIn.json2object(message) match { 
     case message: PostMessage => 
     ... 
     case message: MessageFromIn => 
     ... 
    } 
} 

、あなたは(つまり、あなたが期待するものを言う)コンパイラにヒントを与えることによってそれを得ることができます。

override def receive = { 
    case message: JsValue => 
    (message: WSMessageIn) match { 
     case message: PostMessage => 
     ... 
     case message: MessageFromIn => 
     ... 
    } 
} 

注:abstract class WSMessageIn()sealed trait WSMessageIn

+0

に送信できます。本当にありがとうございます。これは私が知りたかったものです。 – Gianfrance

関連する問題