Hello Hongwei,

Viktor has explained why things fail in your example, but to answer your
two questions:

   1. The timeout describes how long you are willing to wait for a result;
   once that time is up a failed “result” will be created and the waiting time
   is over. If the TestActor shall be informed about this then you’ll need to
   send it a message from a .recover() callback that is added directly to the
   ask-Future.
   2. Your usage of the ask pattern is already correct; one remark, though:
   Future.andThen is only needed for guaranteed ordering of side-effecting
   callbacks (i.e. .foreach()), but in order to use that you’ll have to then
   keep using the Future that is returned from andThen.

Regards,

Roland

On Thu, Aug 13, 2015 at 7:59 PM, Viktor Klang <[email protected]>
wrote:

> you're sending a RequestMessage back instead of a ResponseMessage
>
> --
> Cheers,
> √
> On 13 Aug 2015 18:12, "Hongwei Liu" <[email protected]> wrote:
>
>> hi,
>>
>> i need to start JVM in the akka actor as below.
>>
>>
>> object TestActor {
>>
>>   def main(args:Array[String]) = {
>>
>>     val system = ActorSystem("TestActorSystem")
>>     val requestActor = system.actorOf(Props(classOf[TestActor]), 
>> "request-actor")
>>
>>     val request = "this is request message"
>>     println("TestActor => main => send request : " + request)
>>     ////requestActor ! RequestMessage(request)
>>
>>     val future = requestActor.ask(RequestMessage(request))(12 seconds)
>>
>>     future andThen {
>>       case Success(result: Any) => {
>>         println("Successfully processed the request => result is " + 
>> result.toString)
>>       }
>>       case Failure(error: Throwable) => {
>>         println("Failed to process request => error is " + error.toString)
>>       }
>>     }
>>
>>     future.map {
>>       case ResponseMessage(response:Any) => println("TestActor => main => 
>> ask future response => " + response.toString)
>>     }.recover {
>>       case x : Exception => println("TestActor => future receover exception 
>> => " + x.getMessage)
>>     }
>>
>>     println("end of TestActor.main")
>>   }
>> }
>>
>> case class RequestMessage(request:Any)
>>
>> case class ResponseMessage(response:Any)
>>
>> class TestActor extends Actor {
>>   override def receive: Actor.Receive = {
>>     case RequestMessage(request:String ) => {
>>
>>
>>         var exitValue: Int = 0
>>         var jvm_process: Process = null
>>         var errorText: String = ""
>>         var logText: String = ""
>>
>>         try {
>>           val java_home = System.getProperty("java.home");
>>           val path_separator = System.getProperty("file.separator")
>>           val java_path = java_home + path_separator + "bin" + 
>> path_separator + "java"
>>
>>           val job = TestJob
>>           val testClassPath = System.getProperty("java.class.path")
>>           val testClassName = job.getClass.getCanonicalName.dropRight(1)
>>
>>           println("class name " + job.getClass.getName)
>>
>>           val txt =
>>
>>             "{\"spark\": 
>> {\"master\":\"spark://0.0.0.0:7077\"},\"appName\":\"testApp\"}"
>>
>>           println("raw " + txt)
>>
>>           val ptxt = txt.replace("'", "\"")
>>
>>           println("ptxt " + ptxt)
>>
>>           val defaultConfig = ConfigFactory.parseString(ptxt)
>>
>>           val text = "\"" + 
>> defaultConfig.root().render(ConfigRenderOptions.concise()).replace("\"", 
>> "'") + "\""
>>           println("rendered " + text)
>>
>>           println("command " + java_path + " -cp " + testClassPath + " " + 
>> testClassName + " " + text)
>>
>>           val process_builder = new ProcessBuilder(java_path, "-cp", "\"" + 
>> testClassPath + "\"", "\"" + testClassName + "\"", text)
>>
>>           jvm_process = process_builder.start()
>>
>>           val error_stream_reader = new BufferedReader(new 
>> InputStreamReader(jvm_process.getErrorStream))
>>
>>           val input_stream_reader = new BufferedReader(new 
>> InputStreamReader(jvm_process.getInputStream))
>>
>>           jvm_process.waitFor()
>>
>>           exitValue = jvm_process.exitValue()
>>
>>           println("jvm process exit value : " + exitValue)
>>
>>           errorText = 
>> Stream.continually(error_stream_reader.readLine()).takeWhile(_ != 
>> null).mkString("\n")
>>           println("process error stream :" + errorText)
>>
>>           error_stream_reader.close()
>>
>>           logText = 
>> Stream.continually(input_stream_reader.readLine()).takeWhile(_ != 
>> null).mkString("\n")
>>
>>           println("process input stream :" + logText)
>>
>>           input_stream_reader.close()
>>
>>         }
>>         finally {
>>           if (jvm_process != null) {
>>             jvm_process.destroy()
>>             println("jvm process is destroyed")
>>           }
>>         }
>>
>>         // set return value
>>         val response = "{" + "\"exitValue\":" + "\"" + exitValue + "\"" + 
>> "," + "\"errorText\":" + "\"" + errorText + "\"" + "," + "\"logText\":" + 
>> "\"" + logText + "\"" + "}"
>>         if (exitValue == 0) {
>>           Success(response)
>>         } else {
>>           Failure(new Throwable(response.toString))
>>         }
>>
>>
>>         //must send reponse
>>         *//sender ! RequestMessage(response.toString)*
>>       }
>>
>>   }
>>
>>
>>
>> object TestJob {
>>
>>   def main(args: Array[String]) {
>>     val arg0 = args(0)
>>     println("** TestJob => main => arg " + arg0)
>>
>>     val text = arg0.replace("\"","").replace("'", "\"")
>>     val cfg = ConfigFactory.parseString(text)
>>
>>     println("** TestJob => main => start runJob")
>>     try {
>>       this.runJob(cfg)
>>     } catch {
>>       case x: Throwable => {
>>         println("*** TestJob => runJob throw exception => " + x.getMessage)
>>         throw x
>>       }
>>     }
>>     finally {
>>       //
>>     }
>>     println("** TestJob => main => end runJob")
>>   }
>>
>>   def runJob(config:Config):Any = {
>>
>>     println("### TestJob => runJob => start")
>>
>>     val duration = Duration.create(4, TimeUnit.SECONDS)
>>     Thread.sleep(duration.toMillis)
>>
>>     println("### TestJob => runJob => complete")
>>   }
>> }
>>
>>
>>
>> but when run this test, i get below:
>>
>>
>> TestActor => main => send request : this is request message
>> class name TestJob$
>> raw {"spark": {"master":"spark://0.0.0.0:7077"},"appName":"testApp"}
>> ptxt {"spark": {"master":"spark://0.0.0.0:7077"},"appName":"testApp"}
>> rendered "{'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}"
>> command C:\Program Files\Java\jdk1.8.0_45\jre\bin\java -cp C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\charsets.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\deploy.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\javaws.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jce.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jfr.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jfxswt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jsse.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\management-agent.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\plugin.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\resources.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\rt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\access-bridge-64.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\cldrdata.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\dnsns.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\jaccess.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\jfxrt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\localedata.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\nashorn.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunec.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunmscapi.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunpkcs11.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\zipfs.jar;F:\scala-learning\UseFuture\target\scala-2.10\classes;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-annotations\bundles\jackson-annotations-2.3.0.jar;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-core\bundles\jackson-core-2.3.1.jar;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-databind\bundles\jackson-databind-2.3.1.jar;C:\Users\b-holiu\.ivy2\cache\com.thoughtworks.paranamer\paranamer\jars\paranamer-2.6.jar;C:\Users\b-holiu\.ivy2\cache\com.typesafe\config\bundles\config-1.0.2.jar;C:\Users\b-holiu\.ivy2\cache\com.typesafe.akka\akka-actor_2.10\jars\akka-actor_2.10-2.2.4.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-can_2.10\bundles\spray-can_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-client_2.10\bundles\spray-client_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-http_2.10\bundles\spray-http_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-httpx_2.10\bundles\spray-httpx_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-io_2.10\bundles\spray-io_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-util_2.10\bundles\spray-util_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-ast_2.10\jars\json4s-ast_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-core_2.10\jars\json4s-core_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-jackson_2.10\jars\json4s-jackson_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.jvnet.mimepull\mimepull\jars\mimepull-1.9.5.jar;C:\Users\b-holiu\.ivy2\cache\org.parboiled\parboiled-core\jars\parboiled-core-1.1.7.jar;C:\Users\b-holiu\.ivy2\cache\org.parboiled\parboiled-scala_2.10\jars\parboiled-scala_2.10-1.1.7.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-compiler\jars\scala-compiler-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-reflect\jars\scala-reflect-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scalap\jars\scalap-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-library\jars\scala-library-2.10.5.jar;C:\Program
>>  Files (x86)\JetBrains\IntelliJ IDEA Community Edition 
>> 14.1.2\lib\idea_rt.jar TestJob 
>> "{'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}"
>> end of TestActor.main
>> jvm process exit value : 0
>> process error stream :
>> process input stream :** TestJob => main => arg 
>> {'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}
>> ** TestJob => main => start runJob
>> ### TestJob => runJob => start
>> ### TestJob => runJob => complete
>> ** TestJob => main => end runJob
>> jvm process is destroyed*Failed to process request => error is 
>> akka.pattern.AskTimeoutException: Timed out**TestActor => future receover 
>> exception => Timed out*
>>
>>
>> basically, the code simulate the real task will use 4 seconds(or even longer 
>> in reality)* ,* but the ask pattern will have 12 seconds as time out 
>> limitation.
>>
>>
>> the result actually indicate the TestActor ask patter will timed out.
>>
>>
>> i think this because i did not send back response when receive the 
>> RequestMessage.
>>
>>
>> but after i send the response, i get below:
>>
>>
>> TestActor => main => send request : this is request message
>> class name TestJob$
>> raw {"spark": {"master":"spark://0.0.0.0:7077"},"appName":"testApp"}
>> ptxt {"spark": {"master":"spark://0.0.0.0:7077"},"appName":"testApp"}
>> rendered "{'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}"
>> command C:\Program Files\Java\jdk1.8.0_45\jre\bin\java -cp C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\charsets.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\deploy.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\javaws.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jce.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jfr.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jfxswt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\jsse.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\management-agent.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\plugin.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\resources.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\rt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\access-bridge-64.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\cldrdata.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\dnsns.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\jaccess.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\jfxrt.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\localedata.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\nashorn.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunec.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunmscapi.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\sunpkcs11.jar;C:\Program 
>> Files\Java\jdk1.8.0_45\jre\lib\ext\zipfs.jar;F:\scala-learning\UseFuture\target\scala-2.10\classes;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-annotations\bundles\jackson-annotations-2.3.0.jar;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-core\bundles\jackson-core-2.3.1.jar;C:\Users\b-holiu\.ivy2\cache\com.fasterxml.jackson.core\jackson-databind\bundles\jackson-databind-2.3.1.jar;C:\Users\b-holiu\.ivy2\cache\com.thoughtworks.paranamer\paranamer\jars\paranamer-2.6.jar;C:\Users\b-holiu\.ivy2\cache\com.typesafe\config\bundles\config-1.0.2.jar;C:\Users\b-holiu\.ivy2\cache\com.typesafe.akka\akka-actor_2.10\jars\akka-actor_2.10-2.2.4.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-can_2.10\bundles\spray-can_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-client_2.10\bundles\spray-client_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-http_2.10\bundles\spray-http_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-httpx_2.10\bundles\spray-httpx_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-io_2.10\bundles\spray-io_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\io.spray\spray-util_2.10\bundles\spray-util_2.10-1.3.3.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-ast_2.10\jars\json4s-ast_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-core_2.10\jars\json4s-core_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.json4s\json4s-jackson_2.10\jars\json4s-jackson_2.10-3.2.10.jar;C:\Users\b-holiu\.ivy2\cache\org.jvnet.mimepull\mimepull\jars\mimepull-1.9.5.jar;C:\Users\b-holiu\.ivy2\cache\org.parboiled\parboiled-core\jars\parboiled-core-1.1.7.jar;C:\Users\b-holiu\.ivy2\cache\org.parboiled\parboiled-scala_2.10\jars\parboiled-scala_2.10-1.1.7.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-compiler\jars\scala-compiler-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-reflect\jars\scala-reflect-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scalap\jars\scalap-2.10.0.jar;C:\Users\b-holiu\.ivy2\cache\org.scala-lang\scala-library\jars\scala-library-2.10.5.jar;C:\Program
>>  Files (x86)\JetBrains\IntelliJ IDEA Community Edition 
>> 14.1.2\lib\idea_rt.jar TestJob 
>> "{'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}"
>> end of TestActor.main
>> jvm process exit value : 0
>> process error stream :
>> process input stream :** TestJob => main => arg 
>> {'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}
>> ** TestJob => main => start runJob
>> ### TestJob => runJob => start
>> ### TestJob => runJob => complete
>> ** TestJob => main => end runJob
>> jvm process is destroyed
>> Successfully processed the request => result is 
>> RequestMessage({"exitValue":"0","errorText":"","logText":"** TestJob => main 
>> => arg {'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}
>> ** TestJob => main => start runJob
>> ### TestJob => runJob => start
>> ### TestJob => runJob => complete
>> ** TestJob => main => end runJob"})
>> TestActor => *future receover exception => 
>> RequestMessage({"exitValue":"0","errorText":"","logText":"** TestJob => main 
>> => arg {'spark':{'master':'spark://0.0.0.0:7077'},'appName':'testApp'}
>> ** TestJob => main => start runJob
>> ### TestJob => runJob => start
>> ### TestJob => runJob => complete
>> ** TestJob => main => end runJob"}) (of class RequestMessage)*
>>
>>
>> so the future.map does not have a match.
>>
>>
>> this is weird.
>>
>>
>> so my questions are:
>>
>>
>> 1. what if my real task longer than 12 seconds (the ask pattern timeout) ? 
>> seems will get Timed Out error
>>
>>
>> 2. what's the right way to use Future in akka ask pattern like my scenario?
>>
>>
>>
>> Thank you very much in advance.
>>
>> Hongwei
>>
>> --
>> >>>>>>>>>> Read the docs: http://akka.io/docs/
>> >>>>>>>>>> Check the FAQ:
>> http://doc.akka.io/docs/akka/current/additional/faq.html
>> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Akka User List" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>> Visit this group at http://groups.google.com/group/akka-user.
>> For more options, visit https://groups.google.com/d/optout.
>>
> --
> >>>>>>>>>> Read the docs: http://akka.io/docs/
> >>>>>>>>>> Check the FAQ:
> http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
> ---
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Akka Team
Typesafe - Reactive apps on the JVM
Blog: letitcrash.com
Twitter: @akkateam

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to