I'm doing a few operations on Futures inside an trait.
trait MyTrait {
//Future based operations
}
Instead of using ExecutionContext.Implicits.global for my Future, I want to use one that is defined in my application.conf.
akka {
my-batch-dispatcher {
type = Dispatcher
executor = "fork-join-executor"
fork-join-executor {
parallelism-min = 10
parallelism-factor = 2.0
parallelism-max = 10
}
throughput = 20
}
}
Inside my actor I can do a lookup to get the execution context.
implicit val ec = context.system.dispatchers.lookup("akka.my-batch-dispatcher")
Now sure how to do this inside my trait.
You can add it as abstract implicit value of the trait:
trait MyTrait {
implicit val ec: ExecutionContext
//Future based operations
}
Then the code the implement the trait should make sure to provide the ExecutionContext. If that is an Actor you may do something like:
class MyActor extends Actor with MyTrait {
implicit val ec = context.system.dispatchers.lookup("akka.my-batch-dispatcher")
def receive = {
case "hello" => println("hello back at you")
case _ => println("huh?")
}
}
I didn't test it but I think this should work.
Related
I have an actor of the form:
class TestActor(repo: Repo) extends Actor {
implicit val executionContext: ExecutionContext = context.dispatcher
def receive: Receive = {
...
}
def testMethod(stringSeq: Seq[String]): String =
...
}
}
I want to test the method testMethod only.
I am trying to write the test case as:
class TestActorSpec
extends TestKit(ActorSystem("TestActorSpec"))
with WordSpecLike
with Matchers
with JsonSupport
with MockitoSugar
with BeforeAndAfterAll
with ImplicitSender {
override def afterAll: Unit = TestKit.shutdownActorSystem(system)
implicit val futureDuration: FiniteDuration = 60.seconds
implicit val timeout: Timeout = 10.seconds
val mockedRepo = mock[Repo]
val testActorRef: ActorRef = system.actorOf(
TestActor.props(mockedRepo)
)
"TestActorSpec" should {
"be able to get data " in {
}
}
}
How can i access the method testMethod from testActorRef ?
I also tried:
TestActorRef[TestActor].underlyingActor.testMethod(Seq("data"))
It does not work for me.
Actors should be tested via messages you send to them. But you still can test methods in isolation if the method is not accessing any actor specific values, like context.
You can move testMethod into companion object and test it from there.
class TestActor(repo: Repo) extends Actor {
implicit val executionContext: ExecutionContext = context.dispatcher
def receive: Receive = {
// call TestActor.testMethod
}
}
object TestActor {
def testMethod(stringSeq: Seq[String]): String = ???
}
I am learning Scala and Akka and I came across an example that confused me. The following code sample was in 1 file.
class RestApi(system: ActorSystem, timeout: Timeout) extends RestRoutes {
implicit val requestTimeout = timeout
implicit def executionContext = system.dispatcher
def createBoxOffice = system.actorOf(BoxOffice.props, BoxOffice.name)
}
trait BoxOfficeApi {
import BoxOffice._
def createBoxOffice(): ActorRef
implicit def executionContext: ExecutionContext
implicit def requestTimeout: Timeout
lazy val boxOffice = createBoxOffice()
// Uninteresting methods here
}
The part that confuses me is the createBoxOffice() call in the BoxOfficeAPI trait. It clearly states that the BoxOfficeAPI has a function which will return an ActorRef. However the implementation for that function is located in the RestApi class which doesn't have any reference to the trait.
How is it possible that the trait can access this method? What is the scope of a trait?
How is it possible that the trait can access this method?
I think you're missing the fact that the trait itself has an abstract method called createBoxOffice:
def createBoxOffice(): ActorRef
Which is why it has such a method in scope. It has nothing to do with the declaration of RestApi. Whoever mixes in this trait will have to implement that said method. That means, for example, that if the RestApi class decides to mix in BoxOfficeApi, it already has an implementation available which it will use. For example:
class Baz extends Foo {
override def quuux(): Unit = println("quuux")
}
trait Foo {
def quuux(): Unit
}
Is it possible to create an akka actor that has implicits in the constructor?
Having:
class Actor(parameter: Long)(implicit service:Service)
and
class Service
can I use the context to create the actor like this?
implicit val service:Service = new Service()
val someLong = 3
context.actorOf(FromConfig.props(Props(classOf[Actor], someLong)), "actor")
As a mention the service cannot be passed to the constructor because multiple different actor classes can be received, which use different implicits from the scope.
Define your Props in Companion object of Actor and is good for injecting Dependencies.
class SomeActor(parameter: Long)(implicit service:Service) extends Actor {
def receive = {
case message => // Do your stuff
}
}
object SomeActor {
def props(parameter: Long)(implicit service:Service) = Props(new SomeActor(parameter))
}
implicit val service:Service = new Service()
val someLong = 3
val ref = context.actorOf(SomeActor.props(someLong)), "actor")
and you can read more about Dependency Injection here :
http://doc.akka.io/docs/akka/snapshot/scala/actors.html#Dependency_Injection
http://letitcrash.com/post/55958814293/akka-dependency-injection
Suppose I am testing results of Futures (see below) with specs2.
def f1():Future[String] = {...}
def f2():Future[String] = {...}
I have Matchers[String] to check the results
def m1():Matcher[String] = {...}
def m2():Matcher[String] = {...}
Now I can use implicits to create Matcher[Future[String]].
def fm1():Matcher[Future[String]] = m1.await(retries=2, timeout=2.seconds)
def fm2():Matcher[Future[String]] = m2.await(retries=2, timeout=2.seconds)
So far so good, but I don't like that repeating retries = 2 and timeout = 2.seconds. How can I define them just once and reuse them across all await calls in the spec ?
case class Retry(value:Int) extends AnyVal
case class Timeout(value:Duration) extends Anyval
implicit class MatcherWithImplicitValues[A](m:Matcher[A]) {
def awaitWithImplicitValues(implicit r:Retry, t:Timeout) = {
m.await(retries = r.value, timeout = t.value)
}
}
implicit val retries = Retry(2)
implicit val timeout = Timeout(2 seconds)
m1.awaitWithImplicitValues
I'd like to reduce the boilerplate needed to bind these akka actors.
At current, my code looks like this:
bind(classOf[ActorRef]).
annotatedWith(Names.named("mines")).
toProvider(new TypeLiteral[ActorProvider[MyActor]]() {}).
asEagerSingleton()
I'd like it too look like:
bindActor[MyActor].withName("mines")
I've tried to subclass AbstractModule to squeeze this concept in to no avail.
Pertinent code:
class ActorProvider[T <: Actor] #Inject() ( val key:Key[T], val injector:Injector, val system: ActorSystem ) extends Provider[ActorRef] {
def get = {
system.actorOf(Props(injector.getInstance(key)))
}
}
Check out https://github.com/codingwell/scala-guice/. Here is a sample based on it. It allows for
bindActor[MyActor].withName("mines")
Keep in mind you are binding a non-generic ActorRef and not Actor itself. This will create a binding for #Named("foo") ActorRef. You should never work with Actor directly.
You cannot get Key in the provider. Provider doesn't take any contextual injections like you tried with the Key or e.g. Injection Point. What you can do is create a different instance of the provider for each actor binding and inject it with ActorSystem afterwards. Alternatively you could change the API to include the actor system instance aswell.
trait AkkaModule extends AbstractModule {
// should be:
// this: AbstractModule =>
// see http://lampsvn.epfl.ch/trac/scala/ticket/3564
import ScalaModule._
private def binderAccess = super.binder // shouldn't need super
def bindActor[T <: Actor](implicit m: Manifest[T]) = new ActorBindingBuilder {
//Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
//So we experamentally figured out how many calls up is the source, so we use that
//Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
val mybinder = binderAccess.withSource((new Throwable).getStackTrace()(3))
val self = (mybinder bind classOf[ActorRef]).asInstanceOf[AnnotatedBindingBuilder[ActorRef]]
}
}
object AkkaModule {
class ActorProvider(val name: String) extends Provider[ActorRef] {
#Inject var system: ActorSystem = _
def get = {
system.actorFor(system.name + "/user/" + name)
}
}
trait ActorBindingBuilder {
val mybinder: Binder
val self: AnnotatedBindingBuilder[ActorRef]
def withName(name: String) = {
val provider = new ActorProvider(name)
self.annotatedWith(Names.named(name)).toProvider(provider)
mybinder.requestInjection(provider)
}
}
}
Something like this that leverages scala's type Manifest might work
http://www.scala-lang.org/api/current/scala/reflect/Manifest.html
where Foo is analogous to ActorRef and Bla is analogous to MyActor:
scala> import com.google.inject
import com.google.inject
scala> val binder:inject.Binder = null
binder: com.google.inject.Binder = null
scala> class Foo {}
defined class Foo
scala> class Bla extends Foo {}
defined class Bla
scala> def bind[T <: Foo:Manifest] = binder.bind( classOf[Foo] ).toProvider( new
inject.TypeLiteral[inject.Provider[T]](){} ).asEagerSingleton
bind: [T <: Foo](implicit evidence$1: Manifest[T])Unit
Maybe combine that with implicit conversion to convert a Binder to a MyBinder:
http://daily-scala.blogspot.com/2009/08/implicit-methods.html
class MyBinder {
def bindActor[T <: ActorRef:Manifest]( nameToBind:String ):Unit = ...
}
object MyBinder {
implicit def binderToMyBinder( ...
}
Good luck!