Reputation: 6611
i am new for Akka, i am using Akka 2.3.3
version for creating actors. I am going to create remote actor and trying to access with client. Whenever i am going to run test-case, the following exception will throw:
[INFO] [04/27/2016 07:51:23.727] [Localsystem-akka.actor.default-dispatcher-3] [akka://Localsystem/deadLetters] Message [com.harmeetsingh13.chapter2.messages.SetRequest] from Actor[akka://Localsystem/temp/$a] to Actor[akka://Localsystem/deadLetters] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [04/27/2016 07:51:23.745] [Localsystem-akka.actor.default-dispatcher-3] [akka://Localsystem/deadLetters] Message [com.harmeetsingh13.chapter2.messages.GetRequest] from Actor[akka://Localsystem/temp/$b] to Actor[akka://Localsystem/deadLetters] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
Futures timed out after [10 seconds]
java.util.concurrent.TimeoutException: Futures timed out after [10 seconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:190)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.Await$.result(package.scala:190)
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(SClientIntegrationSpec.scala:18)
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(SClientIntegrationSpec.scala:15)
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(SClientIntegrationSpec.scala:15)
at org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:22)
at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
at org.scalatest.Transformer.apply(Transformer.scala:22)
at org.scalatest.Transformer.apply(Transformer.scala:20)
at org.scalatest.FunSpecLike$$anon$1.apply(FunSpecLike.scala:422)
at org.scalatest.Suite$class.withFixture(Suite.scala:1122)
at com.harmeetsingh13.chapter2.SClientIntegrationSpec.withFixture(SClientIntegrationSpec.scala:11)
at org.scalatest.FunSpecLike$class.invokeWithFixture$1(FunSpecLike.scala:419)
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:431)
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:431)
at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306)
at org.scalatest.FunSpecLike$class.runTest(FunSpecLike.scala:431)
at com.harmeetsingh13.chapter2.SClientIntegrationSpec.runTest(SClientIntegrationSpec.scala:11)
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:464)
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:464)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:413)
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:401)
............
My Server code as below: Main.scala
object Main extends App{
private val configFile = getClass.getClassLoader.getResource("application.conf").getFile;
private val config = ConfigFactory.parseFile(new File(configFile ))
val system = ActorSystem("SimpleClientServer", config)
system.actorOf(Props[AkkadmeyDB], name = "akkademy-db")
}
application.conf:
akka{
actor{
provider = "akka.remote.RemoteActorRefProvider"
}
remote{
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
log-sent-messages = on
log-received-messages = on
}
}
AkkadmeyDB.scala Actor class:
class AkkadmeyDB extends Actor{
val map = new HashMap[String, Object]
val log = Logging(context.system, this)
override def receive: Receive = {
case SetRequest(key, value) =>
log.info("received SetRequest - key: {} value: {}", key, value)
map.put(key, value)
sender() ! Status.Success
case GetRequest(key) =>
log.info("received GetRequest - key: {}", key)
val response = map.get(key)
response match{
case Some(x) => sender() ! x
case None => Status.Failure(new KeyNotFoundException(key))
}
case o => Status.Failure(new ClassNotFoundException())
}
}
Client Code as below: SClient.scala
class SClient(remoteIp: String) {
private implicit val timeout = Timeout(10 seconds)
private implicit val system = ActorSystem("Localsystem")
private val remoteAddress = s"akka.tcp://SimpleClientServer@$remoteIp/user/akkademy-db";
private val remoteDb = system.actorSelection(remoteAddress)
def set(key: String, value: Object) = {
remoteDb ? SetRequest(key, value)
}
def get(key: String) = {
remoteDb ? GetRequest(key)
}
}
SClientIntegrationSpec.scala Test case:
class SClientIntegrationSpec extends FunSpecLike with Matchers {
val client = new SClient("127.0.0.1:2552")
describe("akkadment-db-client"){
it("should set a value"){
client.set("jame", new Integer(1313))
val futureResult = client.get("james")
val result = Await.result(futureResult, 10 seconds)
result should equal (1313)
}
}
}
When i see the logs of my remote application, this seems like, the request hit doesn't go to the server. what is the problem in my sample code running?
Upvotes: 2
Views: 2075
Reputation: 6611
For solving above problem, we need to follow two steps that are metnion below:
When i am creating a server code, i am excluding application.conf
from my server application, that's why, client application not able to connect with server. The code are using in built.sbt
is as below:
mappings in (Compile, packageBin) ~= { _.filterNot { case (_, name) =>
Seq("application.conf").contains(name)
}}
After commenting above code, the client see the server successfully.
In Learning Scala
chapter 2 jasongoodwin
explain the code of client and server actor system. But there are some Errata in book and missing application.conf
configuration for client. Because when we run both code in same PC, we are facing already port bind exception because by default actors are using 2552
port for accessing and we already define this port for our server application. So, application.conf
also need for client as below:
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port = 0
}
log-sent-messages = on
log-received-messages = on
}
}
Here Port 0
means any free port.
After that, above code are running successfully.
Upvotes: 4
Reputation: 11
There is an application.conf file in the client project as well which is not mentioned in the book. Make sure you create that file under the resources folder with the following content:
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
}
See the official github repo
Upvotes: 1