I noticed it is legal to write this scala code:
val fussyActor = actor {
loop {
receive {
case s: String => println("I got a String: " + s)
case _ => println("I have no idea what I just got.")
}
}
}
I know from documentation that actor is a trait, which has loop and receive value members. But how is it possible to stack these methods like above? Is it implementing or overriding these methods? I am quite confused at this syntax. Please provide some good references/pointers.
First, a standard disclaimer. Scala Actors have been deprecated in favor of Akka Actors. If you want to continue down the path of learning to use Actors with Scala, you should look into Akka instead of researching Scala Actors.
Now, about your question. There are a couple of things in play here, so let's first start out with what you need to do in order to define a new Scala Actor. If you look at the Scala Actor trait, you see that there is one abstract method that you must provide called act():Unit. This is a method that takes no inputs and returns no inputs. It defines the actors behavior. So in it's simplest form, a custom Scala Actor could be:
class MyActor extends Actor{
def act(){
}
}
Now this not a very interesting actor as it does nothing. Now, one way to provide behavior is to invoke the receive method, providing a PartialFunction[Any,R] where R is a generic return type. You could do that like so:
class MyActor extends Actor{
def act(){
receive{
case "foo" => println("bar")
}
}
}
So now if this actor receives a message "foo", it will print "bar". The problem here is that this will only happen for the first message and then won't do anything after. To fix that. we can wrap our call to receive with a call to loop to make it continue to do the provided receive call for each received message:
class MyActor extends Actor{
def act(){
loop{
receive{
case "foo" => println("bar")
}
}
}
}
So this is now starting to look like your example a bit more. We are leveraging the loop and receive methods that come with the Actor trait in order to give this actor behavior. Lastly, instead of defining an explicit class as my actor, I can define one on the fly with the actor method on the Actor companion object. That method takes a function body that will be used as the act impl like this:
def actor(body: => Unit){
val a = new Actor {
def act() = body
override final val scheduler: IScheduler = parentScheduler
}
}
So in your example, you are creating a new actor implementation on the fly and providing an impl for act that will loop and call receive continually with the partial function you supplied for message handling.
Hopefully this clarifies things a bit. The only method you are "overriding" (providing an impl for) is act. When you see loop and receive, those are not overrides; they are simply calls to those existing methods on the Actor trait.
Actually it's illegal without import Actor._.
Your code without that import:
val fussyActor = Actor.actor {
Actor.loop {
Actor.receive { ... }
}
}
actor, loop and receive are methods of object Actor.
def actor(body: ⇒ Unit): Actor
def loop(body: ⇒ Unit): Unit
def receive[A](f: PartialFunction[Any, A]): A
Method actor accepts by-name Untit parameter body - some code block to execute in separate thread and creates an Actor with act method implemented using parameter body.
Method loop accepts by-name Untit parameter body - some code block to execute in infinite loop.
Method receive accepts PartialFunction as parameter f and calls f with message as parameter. It takes message from actor associated with current thread.
Note that scala actors are deprecated, you should use akka actors. See The Scala Actors Migration Guide.
Related
The akka documentation is clearly stated that it is dangerous to create an actor within an actor like this:
class ActorA extends Actor {
def receive = ???
}
final class ActorB extends Actor {
def receive = {
case _ =>
val act = context.actorOf(Props(new ActorA))
}}
I understand that the Actor's apply method is accepting this reference of the creating actor. yet I couldn't understand (nor couldn't find any example) why this is harmful and what issues it can cause?
Let's tweak your example a little bit
class ActorA(str:String) extends Actor {
def receive = ???
}
final class ActorB extends Actor {
def receive = {
case _ =>
val act = context.actorOf(Props(new ActorA("hidden")))
}}
Most of the common use case of using actors are to handle failover and supervision, shen an actor fails and needs to be restarted, the actor system needs to know how to do that. When you use Props(Props(new ActorA)), you've hidden the parameter value of "hidden" by handling it yourself.
Rather than doing that if instead, you declare how to create instances of the actor, the actor system will know exactly what it needs to do when recreating an actor -
i.e. create an instance of ActorA with a constructor argument of "hidden".
Even with your example of Actor without param
context.actorOf(Props(new ActorA))
this way of instantiating actors within another actor is not recommended because it encourages to close over the enclosing scope, resulting in non-serializable Props and possibly race conditions (breaking the actor encapsulation).
I believe we are confusing creation and declaration. The doc says that
Declaring one actor within another is very dangerous and breaks actor encapsulation. Never pass an actor’s this reference into Props!
So the problem is declaration, not creation!
Let's look at Java's:
public class MyActor extends AbstractActor {
#Override
public Receive createReceive() {
return ReceiveBuilder.create()
.match(String.class, handleString())
.matchAny(x -> unhandled(x))
.build();
}
private FI.UnitApply<String> handleString() {
return message -> sender().tell("OK", getSelf());
}
class MyOtherActor extends AbstractActor {
#Override
public Receive createReceive() {
return ReceiveBuilder.create()
.match(String.class, handleString())
.matchAny(x -> unhandled(x))
.build();
}
private FI.UnitApply<String> handleString() {
return message -> sender().tell("OK-Inner", getSelf());
}
}
}
Now, if MyOtherActor was a normal class, we'd be able to instantiate it only from an instance of MyActor:
MyActor actor = new MyActor();
MyActor.MyOtherActor otherActor = actor.new MyOtherActor();
Which means that the constructor for MyOtherActor depends on the instance of MyActor!
Now, if Props are supposed to contain the "factory" of the actor. They need a factory method. If our MyOtherActor is declared as we did here, then our props would look like this (ish):
MyActor actor = ??? // how did you even get a reference to the actor and not the actorRef in the first place!
Props otherActorProps = Props.create(MyActor.MyOtherActor.class, () -> actor.new MyOtherActor());
And bang, here comes the kicker! Now your otherActorProps contains a reference to actor, i.e. you have closed over mutable state! If for whatever reason actor "dies", your props will still be referencing it, causing all sort of weirdness.
There is also the issue of how you get a reference to the actor in the first place, and not it's actorRef
IMHO, that's what the documentation is referring to, and not the fact of "creating" (i.e. instantiating, spawning) an actor within another one: that's absolutely normal and it's a routine operation of akka (that's why you can do getContext().actorOf(..) as well as actorSystem.actorOf(...)
The warning is there in the documentation because it's easy to accidentally close over the creating actor's state, including its this pointer (which you should never use in actor-based code).
In my experience, I've usually seen a props method put into an actor's companion object:
object ActorA {
def props() = Props(new ActorA)
}
Doing it that way ensures the returned Props isn't closing over an actor's state.
class ActorB extends Actor {
def receive = {
case _ =>
val actorB = context.actorOf(ActorA.props)
...
}
}
It's not as big of a possibility for actors that don't take constructor parameters, but once parameters come into play you need to be careful about closing over internal state.
This is an continuation of my previous question How do I get around type erasure on Akka receive method
I have 10 type of events which extends from Event that I need to handle.
I want to implement business logic for each event in separate trait, because because mixing all 10 event handler functions will produce several hundreds(if not thousands) lines of code.
I don't want to create different Actor types for each event. For example:
class Event1Actor extend Actor{
def receive ={
case Event1(e) => //event1 Business Logic
}
}
class Event2Actor extend Actor{
def receive ={
case Event2(e) => //event2 Business Logic
}
}
and the same Event3Actor, Event4Actor,etc....
Such code seems ugly to me, because I need to implement business Logic inside each Actor.
Implementing 10 different traits and 10 different Actor classes seems also as bad design.
I'm seeking for some kind generic solution based on design pattern, for example strategy pattern.
case class EventOperation[T <: Event](eventType: T)
class OperationActor extends Actor {
def receive = {
case EventOperation(eventType) => eventType.execute
}
}
trait Event {
def execute //implement execute in specific event class
}
class Event1 extends Event {/*execute implemented with business logic*/}
class Event2 extends Event {/*execute implemented with business logic*/}
hope this is what you are looking for and helps, I have used this patternt to remove the redundant amount of actors wrapping all actions under a single actor executing different type of events.
You could try something like this, which involves auto-composing receive functionality via a base trait. First the code:
case class Event1(s:String)
case class Event2(i:Int)
case class Event3(f:Float)
trait EventHandlingActor extends Actor{
var handlers:List[Receive] = List.empty
override def preStart = {
val composedReceive = handlers.foldLeft(receive)((r,h) => r.orElse(h))
context.become(composedReceive)
}
def addHandler(r:Receive) {
handlers = r :: handlers
}
def receive = PartialFunction.empty[Any,Unit]
}
trait Event1Handling{ me:EventHandlingActor =>
addHandler{
case Event1(s) => println(s"${self.path.name} handling event1: $s")
}
}
trait Event2Handling{ me:EventHandlingActor =>
addHandler{
case Event2(i) => println(s"${self.path.name} handling event2: $i")
}
}
trait Event3Handling{ me:EventHandlingActor =>
addHandler{
case Event3(f) => println(s"${self.path.name} handling event3: $f")
}
}
So you can see in the EventHandlingActor trait we set up a List of type Receive that can be added to by each specific handling trait that we stack into a concrete actor. Then you can see the definitions of the handling functionality for each event defined in a separate trait that is calling addHandler to add another piece of handling functionality. In preStart for any kind of EventHandlingActor impl the receive functions will be composed together with receive being the starting point (empty by default) before hot-swapping out the receive impl with context.become.
Now for a couple of impl actors as an example:
class MyEventHandlingActor extends EventHandlingActor
with Event1Handling with Event2Handling with Event3Handling
case class SomeOtherMessage(s:String)
class MyOtherEventHandlingActor extends EventHandlingActor with Event1Handling{
override def receive = {
case SomeOtherMessage(s) => println(s"otherHandler handling some other message: $s")
}
}
The first one only handles events, so all it needs to do is define which ones it handles my mixing in the appropriate traits. The second one handles one type of event but also some other message that is not an event. This class overrides the default empty receive and provides functionality to handle the non-event message.
If we tested the code like so:
val system = ActorSystem("test")
val handler = system.actorOf(Props[MyEventHandlingActor], "handler")
handler ! Event1("foo")
handler ! Event2(123)
handler ! Event3(123.456f)
val otherHandler = system.actorOf(Props[MyOtherEventHandlingActor], "otherHandler")
otherHandler ! Event1("bar")
otherHandler ! SomeOtherMessage("baz")
Then we would see output similar to this (with the order changing due to asynch handling of messages):
otherHandler handling event1: bar
handler handling event1: foo
handler handling event2: 123
handler handling event3: 123.456
Now, I am asked to add logging function in akka's actor.
When a message is received, before it is handled, this message should be written into log.
And before a message is sent out, this message should be logged first.
I think I should override the receive and send functions in Actor. Suppose I create a trait actorlog which extends Actor. And class myActor extends actorlog. But in myActor, I need to override receive function (it seems it causes problems here). So I am confused what I should do.
PS. I know akka provides logging. But now I need implement this function by myself.
There is a utility to get logging of the received messages in Akka. It's briefly mentioned in the logging documentation. Basically you wrap your receive function in it like this:
def receive = LoggingReceive {
// your normal receive here
}
And then you enable it in your config with:
akka.actor.debug.receive=on
The information will be logged at debug level.
Besides the other answers here, another approach is to use orElse to prepend a partial function to your receive. In that partial function, put the logging in isDefinedAt so it gets called on every message.
For example:
trait ReceiveLogger {
this: Actor with ActorLogging =>
def logMessage: Receive = new Receive {
def isDefinedAt(x: Any) = {
log.debug(s"Got a $x")
false
}
def apply(x: Any) = throw new UnsupportedOperationException
}
}
class MyActor extends Actor with ActorLogging with ReceiveLogger {
def receive: Receive = logMessage orElse {
case ...
}
}
Using orElse is a general approach for composing receive behavior. In most cases I am composing things like this:
def otherBehavior: Receive = {
case OtherMessage => ...
}
class MyActor extends Actor {
def receive = otherBehavior orElse {
case ...
}
}
A good example of the stackable traits approach can be seen in this presentation: http://www.slideshare.net/EvanChan2/akka-inproductionpnw-scala2013
use stackable modificator abstract override for stackable call of receive method.
use new feature of Akka: event-sourced actor system (docs here).
I am playing around with Scala right now and tried to figure out some best practices about how to design classes. (Trying Scala since a week or so.)
Since my Erlang time I am a huge fan of message passing and actor based software. In most Scala examples actor classes are implemented like this:
object Foo
object Bar
class MyActor extends Actor {
def receive = {
case Foo => ...
case Bar => ...
case _ => ...
}
}
But what I learned from my object oriented (interfaces and polymorphism) carrier tells me that this concept is not very flexible.
MyActor could be replaced by MyAdvancedActor but there is no contract which defines which messages an MyActor implementation needs to implement.
When I think about writing Actors in Scala I tend to write a trait which specifies some methods. The MyActor implementation needs to implement this methods in which the can send its own private messages to itself.
With this approach we have a specified interface and can replace the MyActor implementation in a type-safe manner.
In my time of reading scala tutorials and examples I did not come across such an class design. Is it not common sense or are there better ways in doing this in Scala? Or are these tutorials just to small to cover such a topic?
Common practice is to use an algebraic data type in such cases: you could create a sealed base type for all messages like this:
sealed trait MyActorMessages
object Foo extends MyActorMessages
object Bar extends MyActorMessages
But this kind of contract is not enforced by compiler. You could use use Typed Channels to enforce this contract:
class MyActor extends Actor with Channels[TNil, (MyActorMessages, MyActorReply) :+: TNil] {
channel[MyActorMessages] { (req, snd) ⇒
req match {
case Foo ⇒ ...
case Bar ⇒ ... // You'll get a warning if you forget about `Bar`
}
}
}
Compiler will force you (with warning) to process all possible message types (in this case all subtypes of MyActorMessages), and senders will be forced to send only valid messages using <-!- method (with compilation error).
Note that senders can also use unsafe method ! to send invalid messages.
I really like the solution from #senia. It's an effective use of Akka's new Typed Channels feature. But if that solution does not suit you, I can offer something a bit more traditional to the OO world. In this solution you specify the actual message handling behavior for the actor via a strategy implementation that the actor is constructed with. The code would look something like this:
//Strategy definition
trait FooStrategy{
def foo1(s:String):String
def foo2(i:Int):Int
}
//Regular impl
class RegularFoo extends FooStrategy{
def foo1(s:String) = ...
def foo2(i:Int) = ...
}
//Other impl
class AdvancedFoo extends FooStrategy{
def foo1(s:String) = ...
def foo2(i:Int) = ...
}
//Message classes for the actor
case class Foo1(s:String)
case class Foo2(i:Int)
//Actor class taking the strategy in the constructor
class FooActor(strategy:FooStrategy) extends Actor{
def receive = {
case Foo1(s) => sender ! strategy.foo1(s)
case Foo2(i) => sender ! strategy.foo2(i)
}
}
Then to create instances of this actor:
val regFooRef = system.actorOf(Props(classOf[FooActor], new RegularFoo))
val advFooRef = system.actorOf(Props(classOf[FooActor], new AdvancedFoo))
One benefit here is that you are decoupling the business logic of the actor from it's normal message handling behavior. You are letting the actor class just do actor stuff (receive from mailbox, reply to sender, etc...) and then the real business logic is encapsulated in a trait. This also makes it much easier to test the business logic in isolation with unit tests for the trait impls. If you needed actor type stuff in the trait impls, then you could always specify an implicit ActorContext to the methods on FooStrategy, but then you would lose the complete decoupling of actor and business logic.
Like I said earlier, I like the solution from #senia; I just wanted to give you another option that might be more traditional OO.
I am writing a program using Actors in scala in which an actor (Actor1) accepts two numbers as command line arguments and sends a message to another actor Actor2 (which calculates their sum). Actor2 sends the result to Actor1, who prints it on the screen.
class Actor1 extends Actor {
def main(args: Array[String]) {
val n= Integer.parseInt(args(0))
val k= Integer.parseInt(args(1))
val actor2 = new Actor2
actor2 ! (n, k)
}
def act()
{
react{
case num: Integer =>
println(num)
case _=>
println("Sum not received")
exit
}
}
}
class Actor2 extends Actor {
def act(){
loop
{
react
{
case(n:Int, k:Int) =>
val i = n + k
val actor1 = new Actor1
actor1 ! i}
}
}
}
Is it possible to define main() inside the class that extends Actor, and is there any other way to accept command line arguments by the Actor?
It shows the error: class Actor1 needs to be abstract, since method act in trait Reactor of type ()Unit is not defined.
First things first: You should consider using akka instead of the default Scala actors. It's just better.. in pretty much every aspect.
That aside, here are a few answers for your:
Your main method should be in a standalone object (not a companion object). So use something like this: object Main { def main(args:Array[String]) { ... } } and start your program via the Main object/class. (This is due to the definition inside the Actor1 class being non-static and the problem that if you define a companion object the .class filenames collide.)
In your code, something seems to have gone wrong with the brackets - or did you place Actor2 inside the Actor1 class on purpose? It's cleaner, if you just make three separate classes/objects: Actor1, Actor2, Main.
When you create Scala actors, you have to explicitly start them (not so with akka 2.x). So you miss your calls to actor1.start and such. Note that your program will then not terminate before your actors have terminated, so don't wonder if it doesn't stop anymore after you add that.
Finally, some minor hints:
You may want to consider using !? and send back your answer to the original caller, as this also allows you to have a proper termination condition.
Integer.parseInt("0") can be written more simply as "0".toInt