2013-06-25 6 views
6

akka 원격 액터를 사용하여 메시지를 보내려고합니다. 여기서 case 클래스는 생성자에서 인수를 취하는 수퍼 클래스의 하위 클래스입니다. 여기 Akka 원격 액터, 기본 생성자가없는 수퍼 클래스

문제를 재현하기위한 최소한의 예입니다

package com.tuvistavie.testremote 

import akka.actor.{ Actor, ActorSystem, Props, ActorLogging } 
import com.typesafe.config.ConfigFactory 

abstract class Foo(val a: Int) 
case class MessageFoo(override val a: Int) extends Foo(a) 

object Sender { 
    def main(args: Array[String]) { 
    val system = ActorSystem("Sender", ConfigFactory.load.getConfig("sender")) 
    val actor = system.actorFor("akka://[email protected]:2552/user/receiver") 
    actor ! MessageFoo(1) 
    } 
} 

object Receiver { 
    class ReceiverActor extends Actor with ActorLogging { 
    def receive = { 
     case m: MessageFoo => log.debug(m.toString) 
    } 
    } 

    def main(args: Array[String]) { 
    val system = ActorSystem("Receiver", ConfigFactory.load.getConfig("receiver")) 
    val actor = system.actorOf(Props[ReceiverActor], "receiver") 
    } 
} 

이 코드를 실행할 때, 나는 다음과 같은 오류 얻을 :

[ERROR] [06/26/2013 02:53:16.132] [Receiver-9] 
[NettyRemoteTransport(akka://[email protected]:2552)] 
[email protected]://[email protected]:2552] Error[java.io.InvalidClassException: com.tuvistavie.testremote.MessageFoo; no valid constructor] 

내가 메시지를 직렬화 할 수 없기 때문에이 생각을 (부모 생성자로 인해 akka.serialization.JavaSerializer을 사용). 하나 또는 두 개의 메시지 만 있으면 자체 serializer를 작성할 수 있다는 것을 알았지 만 응용 프로그램에는 이처럼 많은 사례 클래스가 있습니다.

원격 액터를 사용하여 이러한 종류의 객체를 전달하는 쉬운 방법이 있습니까?

trait Foo{ 
    val a:Int 
} 
case class MessageFoo(a:Int) extends Foo 

나는 일반적으로 시도하고 경우 클래스와 멀리 클래스 상속에서 체재 : 당신과 같이 구조 조정을하는 경우

답변

8

상황이 작동합니다. 사례 클래스 집합을 추상 형식으로 참조 할 수 있어야하는 경우 대신 특성을 사용합니다. cmbaxter의 대답은 지적처럼

+1

여기에 무슨 일이 일어나고 있는지 설명해 주실 수 있습니까? 질문의'MessageFoo' 나 여러분의 것에는 인수가없는 생성자가 없습니다. 다른 하나는 Java serialization을 사용하지 않는 이유는 무엇입니까? –

+0

@DanielDarabos, 스칼라 케이스 클래스는 직렬화 가능합니다. 케이스 클래스에 대해 생성 된 자바 코드를 보면 직렬화가 가능한 계약을 충족시키는 것을 알 수 있습니다. – cmbaxter

+0

하지만 문제의 사례 클래스를 직렬화 할 수 없습니다. 맞습니까? –

9
class A(a: Int) 
case class C() extends A(1) 

는 케이스 클래스의 슈퍼 클래스가 인수 없음의 생성자가없는이 패턴은, 직렬화에 InvalidClassException에 연결됩니다. cmbaxter의 답변에 따르면이 패턴을 피하는 것이 하나의 해결책입니다.

하지만이 패턴이 잘못 되었나요? 그 이유는 Serializable에 대한 API 문서에 설명되어 있습니다 :

To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.

그래서 문제는 class A가 인수 없음의 생성자가 없다는 것입니다, 플러스 Serializable 없습니다. 그래서 간단한 해결책은 그것을 만드는 것입니다 Serializable!

class A(a: Int) extends Serializable 
case class C() extends A(1) 
+0

은 매력처럼 작동합니다. 특성에 대한 구조 조정에 덧붙여'extend' /'with'를 추가하기 만하면됩니다. – Brett