Akka.io,在类actor上找不到匹配的构造函数

时间:2014-08-05 14:23:37

标签: java sockets akka playframework-2.3

我想要设置Akka演员来处理正在播放的网络插座。

我已经定义了一个简单的actor来通过web socket发送消息:

package actors;
import akka.actor.*;

public class MyWebSocketActor extends UntypedActor {

    public static Props props(ActorRef out) {
        return Props.create(MyWebSocketActor.class, out);
    }

    private final ActorRef out;

    public MyWebSocketActor(ActorRef out ) {
        this.out = out;
    }

    public void onReceive(Object message) throws Exception {
        if (message instanceof String) {
            out.tell(message, self());
        }
    }
}

在Application控制器中,我有了web-socket:

package controllers;
import play.*;
import play.mvc.*;
import akka.util.*;
import views.html.*;
import actors.MyWebSocketActor;
import play.libs.F.*;

public class Application extends Controller {

    public static Result index() {
        return ok(index.render("Your new application is ready."));
    }

     public static WebSocket<String> socket() {
        return WebSocket.withActor(MyWebSocketActor::props);
     }

}

直到现在,一切都按照我的预期运作。现在,在控制器中我试图将消息传递给该actor。我试过了:

public class Messages extends Controller {

    private static final Form<Message> messageForm = Form.form(Message.class);
    @BodyParser.Of(BodyParser.Json.class)

    public static Result list(Integer page) {
        // --- Render
        ActorRef myActor = Akka.system().actorOf(Props.create(MyWebSocketActor.class));
        String message = "test";
        myActor.tell(message, ActorRef.noSender());
        //  
    }

但是出现错误:“无法调用该操作,最终出现错误:java.lang.IllegalArgumentException:在类actors.MyWebSocketActor上找不到匹配的构造函数,用于参数[]。

2014-08-05 05:50:23,503 - [INFO] - from play in pool-4-thread-4 
Listening for HTTP on /0:0:0:0:0:0:0:0:9000

2014-08-05 05:51:02,887 - [ERROR] - from application in New I/O worker #1 


! @6j5b25956 - Internal server error, for (GET) [/] ->

play.PlayExceptions$CompilationException: Compilation error[error: method tell in class ActorRef cannot be applied to given types;]
    at play.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27) ~[na:na]
    at play.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27) ~[na:na]
    at scala.Option.map(Option.scala:145) ~[scala-library-2.11.1.jar:na]
    at play.PlayReloader$$anon$1$$anonfun$play$PlayReloader$$anon$$taskFailureHandler$1.apply(PlayReloader.scala:297) ~[na:na]
    at play.PlayReloader$$anon$1$$anonfun$play$PlayReloader$$anon$$taskFailureHandler$1.apply(PlayReloader.scala:292) ~[na:na]
    at scala.Option.map(Option.scala:145) ~[scala-library-2.11.1.jar:na]
    at play.PlayReloader$$anon$1.play$PlayReloader$$anon$$taskFailureHandler(PlayReloader.scala:292) ~[na:na]
    at play.PlayReloader$$anon$1$$anonfun$reload$2.apply(PlayReloader.scala:325) ~[na:na]
    at play.PlayReloader$$anon$1$$anonfun$reload$2.apply(PlayReloader.scala:325) ~[na:na]
    at scala.util.Either$LeftProjection.map(Either.scala:377) ~[scala-library-2.11.1.jar:na]
    at play.PlayReloader$$anon$1.reload(PlayReloader.scala:325) ~[na:na]
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:107) ~[play_2.11-2.3.1.jar:2.3.1]
    at play.core.ReloadableApplication$$anonfun$get$1.apply(ApplicationProvider.scala:105) ~[play_2.11-2.3.1.jar:2.3.1]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1361) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) ~[scala-library-2.11.1.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) ~[scala-library-2.11.1.jar:na]

2014-08-05 05:51:03,084 - [WARN] - from play in New I/O worker #1 
No application found at invoker init

2014-08-05 06:08:03,586 - [ERROR] - from application in New I/O worker #2 

2 个答案:

答案 0 :(得分:7)

我可以看到的一个问题是,在您的控制器中,您正在尝试实例化MyWebSocketActor的新实例,但您没有给它正确的构造函数信息以允许创建新实例。问题是这一行:

ActorRef myActor = Akka.system().actorOf(Props.create(MyWebSocketActor.class));

在MyWebSocketActor中,您没有no-args构造函数。您有一个构造函数定义为:

public MyWebSocketActor(ActorRef out ) {
    this.out = out;
}

现在,您正在MyWebSocketActor上的静态props方法中正确执行此操作。如果您真的希望能够在控制器中实例化此actor的新实例(而不是查找现有实例),则需要在构造函数中使用ActorRef(称为out传入。如果你有,那么你可以修改你的代码如下:

ActorRef myActor = Akka.system().actorOf(MyWebSocketActor.props(outRef));

修改

现在,如果您想查找现有的actor而不是创建每个请求的actor,您首先需要确保已经创建并命名了要查找的actor实例,以便您可以查看它了。所以像这样:

Akka.system().actorOf(MyWebSocketActor.props(outRef), "myactor");

然后,在您的控制器中,您可以使用ActorSelection找到预先存在的演员,如下所示:

ActorSelection myActorSel = Akka.system().actorSelection("/user/myactor");

ActorSelection不是ActorRef,也不共享某个基接口/抽象类。但它支持tell操作的方式与ActorRef相同,因此您可以在查找后调用tell。如果你的演员存在这个名字,那么事情应该很好。

您可以在“通过ActorSelection识别参与者”一节中阅读有关ActorSelection s here的更多信息。

答案 1 :(得分:3)

你的演员只有一个带参数的构造函数。使用actorOf创建actor时,不会传递该参数。这也是错误消息所说的,你的actor没有不带参数的构造函数。

有趣的是,您在actor中定义了一条静态props消息。如果您使用它而不是在actorOf中创建Props,那么您将获得编译器警告; - )