2017-11-01 1 views
1

스케이프 2.5의 플레이 프레임 워크 2.5에서 websocket을 사용하려고했습니다. 이제 여러 메시지 유형을 교환하고 싶습니다.복수 메시지 유형 - 스칼라가있는 프레임 워크의 websocket에 대한 액터

그러나 클라이언트가 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] 당신의 웹 소켓이 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

관련 문제