Akka Actor Customization for libraries - scala

I want to make a library that is going to be used and configurable by other people, using akka actors.
I want to make a Repository actor to which a type of storage will be injected by the library user like "MemoryDatabase" or "FileDatabase" or anything that extends a defined class or actor (see question 2).
1) What is the best way for a user to specify options (including his own created ones)?
2) Should "MemoryDatabase" be an actor child of repository, or just a normal class as a field/property of the Repository actor in this case?
Thanks!
-Jojolepro
Edit:
I want to make an actor that looks like
class Repository extends Actor{
val repoType:DataStorageType = ...
def receive:Receive={}
}
What I want to know the best way for a end user of such library to specify the repoType field, considering that Repository is already in a predefined actor hierarchy.

It depends on if you want the user to put in a concrete instance or merely a type. Ignoring any kind of DI system you could use, I would merely pass the concrete instance to the actor's constructor via props when the actor is started but then that would depend on the concrete instance being thread safe because not necessarily only that actor would be managing it. If you want the actor to own the repository, have the user pass the factory instance or type to the props and thus the constructor.

Related

Multiple IActor interfaces

I have a need for an Actor to implement multiple interfaces. Is this possible?
Currently, when I attempt to have the Actor type implement an interface that derives from another interface which derives from IActor, I get a message that it implements multiple interfaces, and ActorServiceAttribute needs to be used to distinguish. Adding ActorServiceAttribute does not remove the error message.
[EDIT]
I believe I solved this problem. The errors are confusing. You need to directly implement BOTH interfaces on the Actor type. The build-time discover does not seem to enumerate through the interface hierarchy to find IActor.
Thanks for reporting the issue. Can you provide information on your interface hierarchy. Adding the ActorServiceAttribute on the actor with the valid service name should have resolved the error. By default the actor services are named using the actor interfaces. In this case since there are two different actor interfaces (IBaseActor, IDerivedActor) that are implemented by the actor, runtime cannot determine the naming for the actor service. This is because on the client side, one can create ActorProxy or ActorProxy.

How to restrict access to local actor

I'm searching for encapsulation methods like private for class members. I'd like an actor to provide accept some common harmless messages and privileged that could possible mutate state in undesirable way. I can also build proxy actor that would filter messages based on access policy. But both actors would be still available via full path actor ref. How can I made some actor ref private, that can be accessed only by its parent?
Any actor can be addressed by any other actor so long as the path is known by using ActorSelection.
If you want to restrict certain messages, you can do so with things like package-private.
Say you have DangerousActor and you only want actors defined in the same package to be able to send DangerousMessage, but you also have SafeMessage and you're fine with anyone else in the actor system sending that.
package dangerous
object DangerousActor {
private[dangerous] case object DangerousMessage
case object SafeMessage
}
case DangerousActor extends Actor {
import DangerousActor._
def receive = {
case DangerousMessage =>
case SafeMessage =>
}
}
Only actors also defined in the dangerous package will be able to reference DangerousMessage.

How to pass behavior to Akka actor

I'm building Akka app which will retrieve RSS feeds (XML) from several sites. For each site I will create some class which will transform XML to some generalized object (Scala case class) with common fields from all RSS feeds:
case class RssFeed(title: String, ...)
trait RssTransformer {
def getRssFeed(): Seq[RssFeed]
}
class FooTransformer(...) extends RssTransformer {
override def getRssFeed(): : Seq[RssFeed] = {...}
}
class BarTransformer(...) extends RssTransformer {
override def getRssFeed(): : Seq[RssFeed] = {...}
}
And I want create Akka actors and pass to each of them some implementation of transformer (for example one actor will work with BarTransformer, another with FooTransformer etc).
The problem is that I'm using DI framework (Spring) to initiate actors, so I can't pass transformers through actor`s constructor parameters. The only way is to pass it using some Message, but passing behavior in messages is anti-pattern in Akka.
Can you please advice me how I can solve this problem, or even better if you can give me some adviŅe on how to improve app architecture to avoid this problem?
Thanks
I'm not sure what you mean by "so I can't pass transformers through actor's constructor parameters." With spring you can use the constructor-arg element to provide constructor arguments.
If the problem is you must create Actors using the ActorSystem#actorOf method, one solution would be to define your own Factory Bean that takes an ActorSystem and some Props as constructor arguments and constructs your Actor.

Unit Testing AKKA actors

I am doing a web application with Scala and Akka actors and I'm having some troubles with the tests.
In my case I need to taste an actor who talks with the Database. To do the unit testing I would like to use a Fake Database but I can't replace the new with my desired fake object.
Let's see some code:
Class MyActor extends Actor {
val database = new Database()
def receive = { ... }
}
And in the tests I would like to inject a FakeDatabase object instead Database. I've been looking in Internet but the best that I found is:
Add a parameter to the constructor.
Convert the val database to a var so in the test I could access the attribute by the underlying and replace it.
Both solutions solve the problem but are very dirty.
Isn't a better way to solve the problem?
Thanks!
The two primary options for this scenario are:
Dependency Injection Use a DI framework to inject a real or mock service as needed. In Akka: http://letitcrash.com/post/55958814293/akka-dependency-injection
Cake Pattern This is a Scala-specific way of achieving something akin to dependency injection without actually relying on injection. See: Akka and cake pattern
Echoing the advice here, I wouldn't call injecting the database in the constructor dirty. It might have plenty of benefits, including decoupling actor behaviour from the particular database instance.
However if you know there is only ONE database you will be always using in your production code, then think about defining a package level accessible constructor and a companion object returning a Props object without parameters by default.
Example below:
object MyActor {
def props() : Props = Props(new MyActor(new Database()))
}
class MyActor private[package](database : IDatabase) extends Actor {
def receive = { ... }
}
In this case you will still be able to inject the test database in your tests case (given the same package structure), but prevent users of your code from instantiating MyActor with unexpected database instance.

Getting instance of class used to create an actor in Akka in test

How do I get instance of class I passed to Props when creating an actor with ActorSystem.actorOf? I need that for unit tests to get reference to some properties of the actor, so the actor is local in the same JVM as test.
I don't want to use Akka's test framework because I need the actor live, it's kind of integration tests.
The underlying instance of an Actor subclass is well and truly sealed off from you and you're not going to get at it without mucking with Akka code itself. If you look at the definition of the ActorRef you'll see that it doesn't even contain a reference to the Actor!
Similarly, you cannot instantiate Actor subclasses directly using new.
I guess the Akka designers were serious about the ActorRef / Actor firewall...
The Akka Testkit is made for integration testing. To get access to the internal state of an actor send it a message asking for it. Your actor can reply to the sender which is the TestKit's testActor.