pekko/akka-docs/scala/code/ActorDocSpec.scala
Patrik Nordwall ce128740ab Updated documentation of Actors (Java). See #1435
* Aligned the Java and Scala documentation for Actors
* Implemented hotswap samples in Java, and documented in same way as Scala docs
* Improved Actors (Scala) docs
* Fixed wrong preRestart and postRestart in UntypedActor
* Changed name of Dispatchers.fromConfig to newFromConfig and made it Java friendly
* Added ActorRef.ask with Timeout parameter in addition to the timeoutMillis
2011-12-08 19:30:04 +01:00

258 lines
5.9 KiB
Scala

package akka.docs.actor
//#imports1
import akka.actor.Actor
import akka.event.Logging
//#imports1
//#imports2
import akka.actor.ActorSystem
//#imports2
import org.scalatest.{ BeforeAndAfterAll, WordSpec }
import org.scalatest.matchers.MustMatchers
import akka.testkit._
import akka.util.duration._
//#my-actor
class MyActor extends Actor {
val log = Logging(context.system, this)
def receive = {
case "test" log.info("received test")
case _ log.info("received unknown message")
}
}
//#my-actor
case class DoIt(msg: ImmutableMessage)
case class Message(s: String)
//#context-actorOf
class FirstActor extends Actor {
val myActor = context.actorOf[MyActor]
//#context-actorOf
//#anonymous-actor
def receive = {
case m: DoIt
context.actorOf(new Actor {
def receive = {
case DoIt(msg)
val replyMsg = doSomeDangerousWork(msg)
sender ! replyMsg
self.stop()
}
def doSomeDangerousWork(msg: ImmutableMessage): String = { "done" }
}) ! m
case replyMsg: String sender ! replyMsg
}
//#anonymous-actor
}
//#system-actorOf
object Main extends App {
val system = ActorSystem("MySystem")
val myActor = system.actorOf[MyActor]
//#system-actorOf
}
class ReplyException extends Actor {
def receive = {
case _
//#reply-exception
try {
val result = operation()
sender ! result
} catch {
case e: Exception
sender ! akka.actor.Status.Failure(e)
throw e
}
//#reply-exception
}
def operation(): String = { "Hi" }
}
//#swapper
case object Swap
class Swapper extends Actor {
import context._
val log = Logging(system, this)
def receive = {
case Swap
log.info("Hi")
become {
case Swap
log.info("Ho")
unbecome() // resets the latest 'become' (just for fun)
}
}
}
object SwapperApp extends App {
val system = ActorSystem("SwapperSystem")
val swap = system.actorOf[Swapper]
swap ! Swap // logs Hi
swap ! Swap // logs Ho
swap ! Swap // logs Hi
swap ! Swap // logs Ho
swap ! Swap // logs Hi
swap ! Swap // logs Ho
}
//#swapper
//#receive-orElse
import akka.actor.Actor.Receive
abstract class GenericActor extends Actor {
// to be defined in subclassing actor
def specificMessageHandler: Receive
// generic message handler
def genericMessageHandler: Receive = {
case event printf("generic: %s\n", event)
}
def receive = specificMessageHandler orElse genericMessageHandler
}
class SpecificActor extends GenericActor {
def specificMessageHandler = {
case event: MyMsg printf("specific: %s\n", event.subject)
}
}
case class MyMsg(subject: String)
//#receive-orElse
class ActorDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
"import context" in {
//#import-context
class FirstActor extends Actor {
import context._
val myActor = actorOf[MyActor]
def receive = {
case x myActor ! x
}
}
//#import-context
val first = system.actorOf(new FirstActor)
first.stop()
}
"creating actor with AkkaSpec.actorOf" in {
val myActor = system.actorOf[MyActor]
// testing the actor
// TODO: convert docs to AkkaSpec(Map(...))
val filter = EventFilter.custom {
case e: Logging.Info true
case _ false
}
system.eventStream.publish(TestEvent.Mute(filter))
system.eventStream.subscribe(testActor, classOf[Logging.Info])
myActor ! "test"
expectMsgPF(1 second) { case Logging.Info(_, "received test") true }
myActor ! "unknown"
expectMsgPF(1 second) { case Logging.Info(_, "received unknown message") true }
system.eventStream.unsubscribe(testActor)
system.eventStream.publish(TestEvent.UnMute(filter))
myActor.stop()
}
"creating actor with constructor" in {
class MyActor(arg: String) extends Actor {
def receive = { case _ () }
}
//#creating-constructor
// allows passing in arguments to the MyActor constructor
val myActor = system.actorOf(new MyActor("..."))
//#creating-constructor
myActor.stop()
}
"creating actor with Props" in {
//#creating-props
import akka.actor.Props
val dispatcher = system.dispatcherFactory.newFromConfig("my-dispatcher")
val myActor = system.actorOf(Props[MyActor].withDispatcher(dispatcher), name = "myactor")
//#creating-props
myActor.stop()
}
"using ask" in {
//#using-ask
class MyActor extends Actor {
def receive = {
case x: String sender ! x.toUpperCase
case n: Int sender ! (n + 1)
}
}
val myActor = system.actorOf(new MyActor)
implicit val timeout = system.settings.ActorTimeout
val future = myActor ? "hello"
future.as[String] match {
case Some(answer) //...
case None //...
}
val result: Option[Int] = for (x (myActor ? 3).as[Int]) yield { 2 * x }
//#using-ask
myActor.stop()
}
"using receiveTimeout" in {
//#receive-timeout
import akka.actor.ReceiveTimeout
import akka.util.duration._
class MyActor extends Actor {
context.receiveTimeout = Some(30 seconds)
def receive = {
case "Hello" //...
case ReceiveTimeout throw new RuntimeException("received timeout")
}
}
//#receive-timeout
}
"using hot-swap" in {
//#hot-swap-actor
class HotSwapActor extends Actor {
import context._
def angry: Receive = {
case "foo" sender ! "I am already angry?"
case "bar" become(happy)
}
def happy: Receive = {
case "bar" sender ! "I am already happy :-)"
case "foo" become(angry)
}
def receive = {
case "foo" become(angry)
case "bar" become(happy)
}
}
//#hot-swap-actor
val actor = system.actorOf(new HotSwapActor)
}
}