2
votes

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?

2
hey it's jason goodwin - I saw your tweet. Can you push your code to github? I've checked all of the examples work before publishing that are posted on my github. I'll give you a hand.JasonG
hi @JasonG thanks for you reply. I am not using downloaded code from you repository, i am creating my own according to your chapters. Divide code into two repository server and client. In Server Repo go to Chapter 2 package github.com/harmeetsingh0013/Akka-practice-using-scala and Client repo github.com/harmeetsingh0013/Akka-practice-using-scala-client. As i mention above, the server code is running successfully, but when i am trying to run client test case, then i got and exception as above mention.Harmeet Singh Taara
thanks, i'll check it out later and get back to you.JasonG
Tanks @JasonG, i will be wait for you answer.Harmeet Singh Taara

2 Answers

4
votes

For solving above problem, we need to follow two steps that are metnion below:

  1. 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.

  1. 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.

1
votes

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