Reputation: 85
I want to create a server/client system using akka remoting. At first I create a simple remote Server. (I wrote the code below for testing purposes and to clarify my concepts so it really doesn't do much.)
I want my client to send a username and a password to the server which the server can verify and reply back. At first I create a client actor. From my client object I send this actor the username and password (I use future here). The client actor then uses another future to send this username and password to the server.
The server in my code gets the username and password and prints it out. The problem is I dont get anything back from the server. Since I used a future to send the information to the server, it should reply back with a result. This is where I think I have a conceptual problem. Going through the akka documentation did not clarify this. But I an sure I am messing up something very basic. The server code is:
EDITED after suggestions from TrustNoOne and cmbaxter.
package server
import collection.mutable
import akka.actor._
import com.typesafe.config.ConfigFactory
import shared._
import shared.CaseClass._
object Server extends App {
val system = ActorSystem("ServerSystem",
ConfigFactory.parseString("""
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname = 127.0.0.1
port = 5555
}
}
}
"""))
system.actorOf(Props[ServerActorClass], "ServerActor")
}
class ServerActorClass extends Actor {
def receive = {
case userPass: UserPass => {
sender ! verified()
println(userPass)
}
case testMsg: String => println("Got a msg"+ testMsg)
}
}
The client code is:
package client
import ...
object Client extends App {
val system = ActorSystem("ClientSystem",
ConfigFactory.parseString("""
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname = 127.0.0.1
port = 0
}
}
}
"""))
val clientActor = system.actorOf(Props[ClientActor], name = "ClientActor") //the local actor
implicit val timout = Timeout(50 seconds)
val f = ask(clientActor, UserPass("a","b"))
f.onSuccess {
case GO => println("Got something back from Client actor") //Still doesn't happen!
}
}
class ClientActor extends Actor {
// create the remote actor
val server = context.actorFor("akka.tcp://[email protected]:5555/user/ServerActor")
implicit val timout = Timeout(1 seconds)
def receive = {
case a: String => println("back" + a)
case a: UserPass => {
val f: Future[Any] = (server ? a)
f.onSuccess {
case response: verified => {
println("Got something back from server") //Does happen now!
val asker = sender()
asker ! GO()
}
case response: verificationFailed => {
val asker = sender()
asker ! NO()
}
}
}
}
}
Case classes that are shared by both the client and the server:
package shared
case object CaseClass {
case class verified //Server msg to acknowledge user and pass successful verification
case class verificationFailed //Server msg saying user pass verification failed
case class GO
case class NO
case class UserPass(user:String, pass:String)
I want to know what I am doing wrong. If someone could explain rather than just point out the problem, it would be great, since I am looking to learn.
Upvotes: 0
Views: 461
Reputation: 5546
In the server actor, you're sending the response like this:
sender ! CaseClass.verified
You are actually sending the "verified" class companion object back to the client. You should either make the verified class a case object or send back to the client a verified instance:
sender ! CaseClass.verified()
You are doing other (unrelated) errors:
val replyTo = sender()
)Upvotes: 1
Reputation: 3908
You're exiting without waiting for a response.
implicit val timout = Timeout(50 seconds)
val f: Future[Any] = clientActor ? UserPass("s","a")
f.onSuccess {
case GO => println("Got something back from Client actor") //Doesnt happen!
}
That sets up a handler for a callback, but then your program just exists.
Minimally, you could scala.concurrent.Await.result(f)
Upvotes: 1