Mixins with Akka - scala

I have an actor to which I want inject dependency using mixin. Code:
trait ProductsAware {
def getProducts: List[Product]
}
trait MyActor extends Actor with ProductsAware {
val products = getProducts
...
}
As you can see I'm just trying to decouple MyActor from concrete instance of ProductsAware trait, and provide concrete instance in other place (when creating actor).
And this is concrete implementation of ProductsAware trait:
trait ProductsAwareFirstImpl {
override def getProducts = {List(new Product())}
}
And I want to create new MyActor and inject to MyActor this concrete implementation ProductsAwareFirstImpl:
system.actorOf(Props[MyActor])
The problem is that is not safe at compile time, i.e. anyone can forget to mix the ProductsAwareFirstImplto MyActor

You can use a different Actor Props construction technique, namely the Props(new Actor) as documented here. Just make sure you are careful and not closing over any state, e.g. putting it in a object and calling it via a method should be safe. This is described in the documentation, but a quick mockup would look like this:
object MyActor {
def newActorWithFirstImpl = new MyActor with ProductsAwareFirstImpl
}
//...
system.actorOf(Props(MyActor.newActorWithFirstImpl))

To be sure that some trait is mixed to you actor you may user explicit self type reference:
trait MyActor extends Actor {
self: ProductsAware =>
val products = getProducts
// ...
}
So no one could instantiate MyActor without mixin ProductsAware

Related

Explanation of Scala construct

I am busy with a major refactoring task on some legacy Scala/Akka code, and am being haunted by a construct that I am unable to explain, which is hampering my effort:
trait PerRequestCreator {
this: Actor =>
def perRequest(<some_params>): ActorRef = { body of function }
}
Which is then used as such:
class SomeActor extends PerRequestCreator with Actor {
def processRequest: Route = {
perRequest(<some_params_passed>)
}
}
I am having trouble understanding the this: Actor => ... part of the trait.
It's called self-type, and it expresses a requirement for the PerRequestCreator to be mixed in into something that extends Actor.
It's useful because now you can use anything defined in Actor inside the definition of PerRequestCreator and the compiler will check that you can only extend PerRequestCreator if you also extend Actor.
Example:
class SomeClass extends PerRequestCreator // this won't compile
class SomeClass extends PerRequestCreator with Actor // this is ok
You can read more about it here: https://docs.scala-lang.org/tour/self-types.html

Scala: How to extend an Akka actor?

I wrote an Akka base-actor that can handle some common messages. I want to reuse this basic behavior in a sub-actor, by extending the base-actor (not by composition of the base-actor).
I have seen several approaches in previous questions. They are all valid but also may be improved:
How extend behaviour of super actor in akka
and
How do I best share behavior among Akka actors?
To make the implementation cleaner, I am trying to achieve the following:
When defining the sub-actor, I try to extend only the base-actor (not both Actor and sub-actor). However, I was not able to force the compiler to do this.
I also try to not rename the receive partial function, because it is a kind of convention.
Here is a sample of my implementation:
//This is the base-actor that implements the common behavior
trait BetterActor extends Actor {
abstract override def receive = {
super.receive orElse { case _ => println("Missing pattern!") }
}
}
//This is the actor that implements the additional behavior.
//I actually wanted to extend BetterActor. It was not possible.
class MyActor extends Actor {
def receive = {
case i: Int =>
println(s"Yay!!! Got $i")
}
}
Here are two alternative ways how I can create an instance of the sub-actor, which combines both the common and the additional behaviors:
//1.
val myBetterActor = system.actorOf(Props(new MyActor with BetterActor), "myBetterActor")
//2.
class MyBetterActor extends MyActor with BetterActor
val myBetterActor = system.actorOf(Props[MyBetterActor], "myBetterActor")
Finally, I may invoke the sub-actor by:
myBetterActor ! 2
myBetterActor ! "a"
Problems with my implementation:
When I create an instance of the sub-actor, only then I can mix in the base-actor, either directly (1) or by defining a new class that mixes in the base-actor.
Like I said before, I would prefer to mix in the base-actor when I define the sub-actor. Not when I try to create an instance of the sub-actor.
P.S. It's fascinating that the designers of this framework did not see it necessary to make this common requirement easy to accomplish.
i suppose as long as you're not trying to override behavior with BetterActor, you could try something like this:
trait BetterActor extends Actor {
override def unhandled(message: Any): Unit = message match {
case e: CommonMessage => println("COMMON!")
case e => super.unhandled(e)
}
}
class MyActor extends BetterActor {
override def receive = {
case i: Int => println(s"Yay!!! Got $i")
}
}

Syntax to dynamically add mixin to an actor

I have an actor that sends messages to another actor. It also creates this other actor and does not know its type at compile time. On creation it needs to add a mixin. I am wondering how to solve this syntactically. So for example if we have:
trait MyMixin extends Actor {
abstract override def receive = {
case msg =>
// Do something
super.receive(msg)
}
}
class Sender(targetClass: Class) extends Actor {
// Here I want to create the actor such that I can add the mixin
// eg. If I knew the class at compile time I could do the following:
// val target = context.actorOf(Props(new TargetActor with MyMixin))
val target = context.actorOf(Props(???))
target ! someMsg
...
}
So the question is how to combine the two classes for a run time creation?
Thanks
Des

Retrieving an ActorSelection from a Trait in akka/scala

I am new to scala/akka. I need to create a trait and from this trait, to retrieve actors from a context or directly from an actorSystem.
But I don't want this trait to either extends Actor, nor force to be mixed with an Actor.
Is there a way to do that?
Thanks.
Welcome to Akka :-)
You should create a trait with an abstract method, that will be used to retrieve the actor system, for example like this:
trait DoesThings {
def system: ActorSystem
def findActor(name: String) = // do actor selection using system here
}
object Example extends DoesThings {
val system = ActorSystem("example")
val ref = findActor
}
Happy hakking!
You can put an actor system val in the trait.
And with instantiation you will pass used actor system to it.
You could try something like this:
trait ActorLookup{
def actorSelection(path:ActorPath)(implicit fact:ActorRefFactory) = fact.actorSelection(path)
def actorSelection(path:String)(implicit fact:ActorRefFactory) = fact.actorSelection(path)
}
class ActorBasedImpl extends Actor with ActorLookup{
def receive = {
case _ =>
val ref = actorSelection("/foo")
}
}
class NonActorBasedImpl extends ActorLookup{
implicit val system = ActorSystem("foo")
...
val ref = actorSelection("/user/foo")
}
Within an Actor, you already have an implicit ActorRefFactory in scope so no need to define one. If you wanted to use the ActorSystem instead there, you could just pass it explicitly like so:
actorSelection("/user/foo")(context.system)
Outside an Actor, it's more likely you will be using an ActorSystem instead of an ActorContext to perform lookups, so that's why an implicit ActorSystem was defined. But again, you don't have to define it as an implicit and could just use it explicitly if desired.

Scala: How can I mock this function using Mockito?

I am wanting to test one of my akka actors, it uses slick to get the information from the database. In my actor I have this bit of code
CardStationPermissions.retrieveByStationID(stationID).foreach(card => {
I want to know how can I mock that function to change the output instead of relaying on whats in the database?
It's really difficult to mock things that are being called in a static way (in this case, a call on an object as opposed to an instance of a class). When you need to be able to mock and test things like this, I tend to agree with Mustafa's suggestion that creating a trait to represent the relevant methods to mock. A simple example would look as follows:
case class MyObject(id:Long)
trait MyDao{
def getData(input:String):List[MyObject] = ...
}
object MyDao extends MyDao
class MyActor extends Actor{
val myDao:MyDao = MyDao
def receive = {
case param:String => sender ! myDao.getData(param)
}
}
Here you can see that I have a trait to represent my dao methods (only 1 for this example) and then I mix that trait into a scala object as the default instantiation of that trait. When I setup my dao in my actor, I explicitly type it to the trait so that I can substitute a mock impl of that trait later.
So then if I wanted a simple test showing mocking, it could look something like this (via specs2):
class MyActorTest(_system:ActorSystem) extends TestKit(_system)
with Specification with Mockito with ImplicitSender{
def this() = this(ActorSystem("test"))
trait scoping extends Scope{
val mockDao = mock[MyDao]
val actor = TestActorRef(new MyActor{
override val myDao = mockDao
})
}
"A request to get data" should{
"pass the input to the dao and return the result to the sender" in new scoping{
mockDao.getData("foo") returns List(MyObject(1))
actor ! "foo"
expectMsg(List(MyObject(1)))
}
}
}