Extracting helper static methods into objec - scala

I have some class:
class MyActor extends Actor{
override def receive: Receive = {
case s: String => doSome()
case i: Int => //something else
}
}
object MyActor{
def doSome() = //some action
}
Is it an idiomatic way in Scala? I did that to simplify testing the Actor. I dont want to create ActorSystem and write integration test in my specific case.
Is it common to do so?

No, the idiomatic way is to extract those methods into a trait, and have the actor extend that trait:
trait DoSomething {
def doSome() = {
println("Doing something")
}
}
class MyActor extends Actor with DoSomething {
override def receive: Receive = {
case s: String => doSome()
case i: Int => //something else
}
}

Related

Call body of all traits inherited

Say I have the below:
type Receive = PartialFunction[Any, Unit]
trait Functionality {
/**
* A set containing all Receive functions
*/
var allReceives: Set[Receive] = Set[Receive]()
}
Now other trait's can extend Functionality and do awesome stuff. Example:
trait LoadBalancer extends Functionality{
def body:Receive = {
case ...
}
allReceives += body
}
And ultimately my class:
class Main with LoadBalancer with SecurityFunctionality
with OtherFunctionality with Functionality{
def receive = {
case x if allReceives.foldLeft(false) { (z, f) => if (f isDefinedAt x) { f(x); true } else z } == true => ()
}
def body: Receive = {
}
allReceives += body
}
Question: What I wish to do is, in Main I need to call body function of all the traits that I have inherited. This way my code can be loosely coupled and I can add/remove functionality at a go.
The above works, but I do not like it as the compiler cannot guarantee that any trait that extends Functionality should add its body to allReceives.
I cannot declare def body:Receive in Functionality as then my implementation in Main will override body implementations of other traits. I am sure there should be a smarter way!
On second thought, composition really might be a better option here. This is a simpler solution, without any funny "abstract override"s:
object Main {
type Receive = PartialFunction[Any, Unit]
trait Receiver {
def receive: Receive
}
class LoadBalancer extends Receiver {
override def receive: Receive = {
case "one" => println("LoadBalancer received one")
}
}
class OtherFunctionality extends Receiver {
override def receive: Receive = {
case "two" => println("OtherFunctionality received two")
}
}
class MainFunctionality extends Receiver {
override def receive: Receive = {
case "three" => println("MainFunctionality received three")
}
}
class CompositeReceiver(receivers: List[Receiver]) extends Receiver {
override def receive: Receive = {
case msg =>
receivers.find(_.receive.isDefinedAt(msg)) map (_.receive(msg))
}
}
def main(args: Array[String]) {
val main = new CompositeReceiver(List(new OtherFunctionality, new LoadBalancer, new MainFunctionality))
main.receive("one")
main.receive("two")
main.receive("three")
}
}
This does not really answer your question, but here is a solution using the stackable traits pattern. Alas you still need to call super.receive as the last case in each trait, but I could not find a way around that yet.
object Main {
type Receive = PartialFunction[Any, Unit]
trait Receiver {
def receive: Receive
}
trait LoadBalancer extends Receiver {
abstract override def receive: Receive = {
case "one" => println("LoadBalancer received one")
case msg => super.receive(msg)
}
}
trait OtherFunctionality extends Receiver {
abstract override def receive: Receive = {
case "two" => println("OtherFunctionality received two")
case msg => super.receive(msg)
}
}
class Main extends Receiver {
override def receive: Receive = {
case "three" => println("Main received three")
}
}
def main(args: Array[String]) {
val main = new Main with OtherFunctionality with LoadBalancer
main.receive("one")
main.receive("two")
main.receive("three")
}
}

How to use stackable trait pattern with Akka actors?

I'm trying to implement a Pub/Sub trait to mix into other akka actors using a stackable trait.
Here is what I came up with:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
At which point, the compiler throws back an error:
error: overriding method receive in trait MyActor... method receive needs `abstract override' modifiers.
Can you explain to me why this isn't working? How can I fix it so it works?
Thanks!
UPDATE
The following works:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
class MyActorImpl extends MyActor with PubSubActor
But why? Why can I get the behavior I want this way but not the other? Any reasons? I can't seem to figure out the underlying difference between these two samples that makes the difference.
There's a simple and concise solution:
Define a Receiving trait that chains multiple receive functions using orElse :
trait Receiving {
var receivers: Receive = Actor.emptyBehavior
def receiver(next: Actor.Receive) { receivers = receivers orElse next }
def receive = receivers // Actor.receive definition
}
Using this in actors is easy:
trait PubSubActor extends Receiving {
receiver {
case Publish => /* I'm the first to handle messages */
}
}
class MyActor extends PubSubActor with Receiving {
receiver {
case SomeMessage => /* PubSubActor didn't handle, I receive the message */
}
}
First PubSubActor's receive will be called. If message wasn't handled it will be passed to MyActor's receive.
You can certainly achieve what you are looking for using Akka's composable actor feature. This is described a bit in Extending Actors using PartialFunction chaining.
First, the infrastructure code (straight from the docs):
class PartialFunctionBuilder[A, B] {
import scala.collection.immutable.Vector
// Abbreviate to make code fit
type PF = PartialFunction[A, B]
private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)
private def mapPfs[C](f: Vector[PF] => (Option[Vector[PF]], C)): C = {
pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {
case (newPfsOption, result) => {
pfsOption = newPfsOption
result
}
}
}
def +=(pf: PF): Unit =
mapPfs { case pfs => (Some(pfs :+ pf), ()) }
def result(): PF =
mapPfs { case pfs => (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) }
}
trait ComposableActor extends Actor {
protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]
final def receive = receiveBuilder.result()
}
Then the behaviors you want to be able to compose into actors:
trait PubSubActor { self:ComposableActor =>
receiveBuilder += {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
trait MyActor { self:ComposableActor =>
receiveBuilder += {
case SomeMessage(a, b, c) => /* ... */
}
}
And lastly, an actual actor that uses these composable behaviors:
class MyActorImpl extends ComposableActor with PubSubActor with MyActor
Try it the other way around:
object Subscription {
case object Subscribe
case object Unsubscribe
}
trait Subscription {
this: Actor =>
import Subscription._
var subscribers = Set.empty[ActorRef]
def receive: Receive = {
case Subscribe => subscribers += sender
case Unsubscribe => subscribers -= sender
}
}
class MyActor extends Actor with Subscription {
def receive = super.receive orElse {
case msg => // handle msg
}
}
Note that this still makes use of the stackable trait pattern, which is hidden by the fact that I've omitted the core. So something like this would still work (at least I think I will, ATM I have no time to check if it compiles).
class Core extends Actor {
def receive = Actor.emptyBehavior
}
class MyActor extends Core with Subscription
BTW, you can read more about the pattern (not related to Actors) here.
For the first, excuse me for my English
I think the point is that abstract override modifier requires presence of concrete implementation of receive method but in the first construction
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
it is not done
The reason is that scala compiler makes linearization for inheritance
so in receive's method chain we have the following sequence:
1) override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
2) abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive cannot be called because it use super.receive,
in its turn super.receive relies on Actor.receive, but Actor.receive hasn't an implementation.
In the second construction
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
class MyActorImpl extends MyActor with PubSubActor
we have receive's method chain
1)
abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
2)
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive can successfully call super.receive
Additional info:
Stackable traits
Scala language specification, see 5.1.2

Problems with multiple trait mixins and Actors

trait A extends Actor {
private val s = Set[Int]()
override def act() {
loop {
react {
// case code that modifies s
}
}
}
}
trait B extends Actor {
private val t = Set[String]()
override def act() {
loop {
react {
// case code that modifies t
}
}
}
}
val c = new C with A with B //...?
What I really want is some sort of auto-combining of B.act() and C.act(), but with trait mix-ins, only B.act() will be called. Is there an easy way to accomplish this?
EDIT: Here is a half-solution I've found. I say 'half' because the original traits no longer extend Actor, and C with A with B needs to be defined as a class as opposed to dynamic mixing-in. Maybe I should call it a 'quarter-solution'?
Maybe you could make a trait that forwards the message on to a list of other Actors, so that you don't have to modify A or B:
trait C extends Actor {
private val acts: Seq[Actor] = Seq(new A{}, new B{})
override def act() {
acts foreach (_.start)
loop {
react { case x => acts foreach { _ ! x } }
}
}
}
You could of course leave acts abstract or override it with a different set when you instantiate this.
Extending the Actor class:
import actors.Actor
class MixableActor extends Actor {
protected var acts = List[PartialFunction[Any, Unit]]()
final override def act() {
loop {
react {
acts.reduce((a, b) => a orElse b)
}
}
}
final def receive(act: PartialFunction[Any, Unit]) {
acts = act :: acts
}
}
Sample Code:
abstract class Node extends MixableActor {
...
}
trait User extends MixableActor {
val files = scala.collection.mutable.Set[Data]()
}
trait Provider extends User {
receive({
case ("provide", file: Data) =>
provide(file)
}: PartialFunction[Any, Unit])
}
trait Consumer extends User {
receive({
case ("consume", file: Data) =>
consume(file)
}: PartialFunction[Any, Unit])
}
Sample Usage:
val provider = new Node with Provider
val consumer = new Node with Consumer
val provider_and_consumer = new Node with Provider with Consumer

Composing trait behavior in Scala in an Akka receive method

Consider these two traits:
trait Poked extends Actor {
override def receive = {
case Poke(port, x) => ReceivePoke(port, x)
}
def ReceivePoke(port: String, x: Any)
}
trait Peeked extends Actor {
override def receive = {
case Peek(port) => ReceivePeek(port)
}
def ReceivePeek(port: String)
}
Now consider I can create a new Actor that implements both traits:
val peekedpoked = actorRef(new Actor extends Poked with Peeked)
How do I compose the receive handlers? i.e., the receiver should be something like the following code, though "automatically generated" (i.e., all traits should compose):
def receive = (Poked.receive: Receive) orElse (Peeked.receive: Receive) orElse ...
You can use super[T] to reference members of particular super classes/traits.
For example:
trait IntActor extends Actor {
def receive = {
case i: Int => println("Int!")
}
}
trait StringActor extends Actor {
def receive = {
case s: String => println("String!")
}
}
class IntOrString extends Actor with IntActor with StringActor {
override def receive = super[IntActor].receive orElse super[StringActor].receive
}
val a = actorOf[IntOrString].start
a ! 5 //prints Int!
a ! "Hello" //prints String!
Edit:
In response to Hugo's comment, here's a solution that allows you to compose the mixins without having to manually wire their receives together. Essentially it involves a base trait with a mutable List[Receive], and each mixed-in trait calls a method to add its own receive to the list.
trait ComposableActor extends Actor {
private var receives: List[Receive] = List()
protected def registerReceive(receive: Receive) {
receives = receive :: receives
}
def receive = receives reduce {_ orElse _}
}
trait IntActor extends ComposableActor {
registerReceive {
case i: Int => println("Int!")
}
}
trait StringActor extends ComposableActor {
registerReceive {
case s: String => println("String!")
}
}
val a = actorOf(new ComposableActor with IntActor with StringActor).start
a ! 5 //prints Int!
a ! "test" //prints String!
The only thing to keep in mind is that the order of the receives should not be important, since you won't be able to easily predict which one is first in the chain, though you could solve that by using a mutable hashmap instead of a list.
You can use empty Receive in base actor class and chain receives in their definitions.
Sample for Akka 2.0-M2:
import akka.actor.Actor
import akka.actor.Props
import akka.event.Logging
import akka.actor.ActorSystem
class Logger extends Actor {
val log = Logging(context.system, this)
override def receive = new Receive {
def apply(any: Any) = {}
def isDefinedAt(any: Any) = false
}
}
trait Errors extends Logger {
override def receive = super.receive orElse {
case "error" => log.info("received error")
}
}
trait Warns extends Logger {
override def receive = super.receive orElse {
case "warn" => log.info("received warn")
}
}
object Main extends App {
val system = ActorSystem("mysystem")
val actor = system.actorOf(Props(new Logger with Errors with Warns), name = "logger")
actor ! "error"
actor ! "warn"
}

Inherit message handling behaviour

I have some events in my model and some handling logic. I want organize communication logic throw Actors. But how I can inherit handling logic without specifying act() in each concrete class
Simplified example
class Event {}
case class FooEvent(str : String) extends Event
case class BarEvent(i : java.lang.Integer) extends Event
trait FooListener extends Actor {
def act() {
react{
case FooEvent => print("foo received")
}
}
}
trait BarListener extends Actor {
def act() {
react{
case BarEvent => print("bar received")
}
}
}
class ListensOnlyBar extends BarListener{}
//can't be done:
//error: overriding method act in trait FooListener of type ()Unit;
//method act in trait BarListener of type ()Unit needs `override' modifier
//class ListensBarAndFoo extends FooListener with BarListener{
class ListensBarAndFoo extends FooListener with BarListener{}
react expects PartialFunction[Any, Unit] and you can nicely compose them together. Here is an example:
type Listener = PartialFunction[Any, Unit]
val foo: Listener = {
case FooEvent => print("foo received")
}
val bar: Listener = {
case BarEvent => print("bar received")
}
case class GenericListener(listener: Listener) extends Actor {
def act() {
react(listener)
}
}
GenericListener(bar)
GenericListener(foo orElse bar)