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.
Related
How to properly pass many dependencies (external APIs) to a class in Scala?
I'm working on the application that uses many APIs to collect data. For API's I have trait like below.
trait api {
def url: Foo
def parse: Bar
}
Also, there are about 10 implementations of the api trait (one for each API). Inside a parent actor, I want to create a child actor for every external API. I created new trait and implementation,
trait ExternalApis {
val apiList: List[api]
}
object MyApis extends ExternalApis {
val apiList = List(new ApiImpl1, ..., new ApiImpl10)
}
so now I can pass MyApis object (or any other implementation of ExternalApis) to parent actor and map over apiList for creating such child actors.
It seems to me I'm missing something. Are there more proper ways to do it?
The implementation that you have made looks nearly ready. Just something I would like to add are:
Passing an API List may not be the most ideal way to do such a thing. Anytime you would like to add/remove something to the API list, you would have to change different areas of the code. A suggestion would be to read this from a config folder, where the config folders would contain things such as url, username, password etc.
If you could provide more insight on the usage of these API's, it would help my answer a lot.
Hope this helped!
I am building a market simulator using Scala/Akka/Play. I have an Akka actor with two children. The children need to have specific types which I would like to specify as parameters.
Suppose that I have the following class definition...
case class SecuritiesMarket[A <: AuctionMechanismLike, C <: ClearingMechanismLike](instrument: Security) extends Actor
with ActorLogging {
val auctionMechanism: ActorRef = context.actorOf(Props[A], "auction-mechanism")
val clearingMechanism: ActorRef = context.actorOf(Props[C], "clearing-mechanism")
def receive: Receive = {
case order: OrderLike => auctionMechanism forward order
case fill: FillLike => clearingMechanism forward fill
}
}
Instances of this class can be created as follows...
val stockMarket = SecuritiesMarket[DoubleAuctionMechanism, CCPClearingMechanism](Security("GOOG"))
val derivativesMarket = SecuritiesMarket[BatchAuctionMechanism, BilateralClearingMechanism](Security("SomeDerivative"))
There are many possible combinations of auction mechanism types and clearing mechanism types that I might use when creating SecuritiesMarket instance for a particular model/simulation.
Can I specify the type parameters that I wish to use in a given simulation in the application.conf file?
I see two questions here.
Can I get a Class instance from a String?
Yes.
val cls: Class[DoubleAuctionMechanism] = Class.forName("your.app.DoubleAuctionMechanism").asInstanceOf[Class[DoubleAuctionMechanism]]
You would still need the cast, as forName returns Class[_].
Can I instantiate a type with type parameters are not known compile time?
Well sort of, but not really.
object SecuritiesMarket {
def apply[A, C](clsAuc: Class[A], clsClr: Class[C])(security: Security): SecuritiesMarket[A, C] = {
SecuritiesMarket[A, C](security)
}
}
I think auction mechanisms and clearing mechanisms are dependencies for SecurityMarket. I'm guessing you instantiate them in its constructor somehow (how?). If that's the case why not just pass them in as a constructor parameter?
Edit:
I don't see how I could create the child actors inside SecurityMarket
Answering this in the comments; Props[T] can also be written as Props[T](classOfT), which can be simplified as Props(classOfT). Those three are the same. So the following code:
val auctionMechanism: ActorRef = context.actorOf(Props[A], "auction-mechanism")
Can be replaced with:
val classOfA = Class.forName("path.to.A")
val auctionMechanism: ActorRef = context.actorOf(Props(classOfA), "auction-mechanism")
First, application.conf is a runtime artifact and its contents are as far as I know not normally parsed at compile time. When the file is parsed at runtime, the parser creates an instance of the class Config which then controls the Akka setup.
The Typesafe Config library project readme is quite nice and the linked documentation has all of the details:
https://github.com/typesafehub/config/blob/master/README.md.
Second, since template parameters are not available at runtime because of type erasure, you can't normally use application.conf to control templating. You could create a custom build step to parse application.conf and modify your code before compilation, but this is maybe not what you want. (And if you do want a custom build step, perhaps a different .conf would be appropriate.)
Instead you might try simply eliminating the type parameters for the securities market class. Then create a single, simple implementation of the auction and clearing actors. Implement these actors by reading the names of the respective mechanisms from application.conf, instantiating the configured mechanism reflectively, and delegating to the instantiated mechanism. The mechanism classes could be independent of Akka, which is perhaps nice if that's where you keep most of your logic?
Update: I've rewritten it in wonky-style and posted it on github - I would appreciate some feedback: https://github.com/drozzy/parallel-discrete-event-akka/tree/master/src/main/scala
Can anyone help me re-write "Parallel discrete event simulation" example from the "Chapter 32: Actors and Concurrency" from Programming in Scala, 2nd, by Martin Odersky?
It was written originally in Scala actors, but translating to Akka I encouter a lot of problems.
Some examples
Actor inheritance (p. 708)
Code like this:
trait Simulant extends Actor
class Wire extends Simulant
I have no idea how to translate to Akka, since in my understanding we never directly instantiate them.
Main Loop
The author constantly uses loops in actors, and I have no idea what they are about:
def act() {
loop {
if (running && busySimulants.isEmpty)
advance()
reactToOneMessage()
}
}
Types
Mostly though, I am struggling with strong types -- it seems Akka, due to requiring ActorRefs prevents me from depending on a specific type of an actor. For example, in the book, the following:
trait Simulant extends Actor {
val clock: Clock
...
depends on a strongly-typed actor Clock. And then it is simply "instantiated" in the implementing actor:
class Wire(name: String, init: Boolean) extends Simulant {
def this(name: String) { this(name, false) }
def this() { this("unnamed") }
val clock = Circuit.this.clock
In my implementation I have something along the lines of:
trait Simulant extends Actor {
val clock: ActorRef
...
and I have no idea how to "instantiate" it. What I have now (untested) is:
class Wire(val clock:ActorRef, name:String, init: Boolean) extends Actor{
def this(clock:ActorRef, name:String) {this(clock, name, false)}
def this(clock:ActorRef){this(clock, "unnamed")}
so I just end up draggin the actor refs around the constructors!
Hooking up components
How do I hook up components to each other? For example, hook-up an AndGate to a Wire - such that any time a signal on the wire changes it sends a message to the gate.
I do it by sending Add messages (i.e. AndGate sends Add to Wire so that wire can add it to the list of its subscribers), and so have to wait for all of them to arrive before starting the simulation. Is there any way to avoid that (the waiting)? (In original implementation the with Scala Actors, some actors were just accessed from global scope, and sometimes actors called other actor's methods directly!)
Source Code
The source code of the example can be found in full at the following url:
http://booksites.artima.com/programming_in_scala_2ed/examples/html/ch32.html
under the heading: 32.6 A longer example: Parallel discrete event simulation
P.S.: I'm new to akka, so forgive my ignorance.
I can not provide any migrated source code, but this link might help you:
actors migration guide.
Some comments:
Actor Inheritance
You can do this in Akka, but class Wire has to implement the receive method.
Main Loop
In Akka you implement the receive method instead of the main loop.
Types
You can use an ActorRef as constructor parameter, but it has to be created (and started) before calling the constructor, e.g. with context.system.actorOf(...).
And there is something called Typed Actors in Akka.
I also strongly encourage you to have a look at the documentation.
EDIT
I had a (quick) look at the source code, these are my findings:
In Scala it is not so common as in Java (and not enforced) that only one public class exists per file (although it can improve compile speed).
Demo.scala: Line 11, Use var instead of val
Constructor initialization (e.g. in FullAdder, Gate, ...): You should be careful about
that, because the constructor is executed every time the actor is restarted; maybe using
the preStart method would be better.
FullAdder, HalfAdder: An actor who doesn't react to messages (or only returning Unit) is a
strange thing in my opinion. Maybe you find another solution for constructing an adder.
Clock.advance: Using return is not good scala style (and I believe it doesn't work
in this case). Use else instead.
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.
I am using Guava's EventBus in my Scala project.
I have a parameterized event like so:
class MyEvent[T]
And a simple event listener:
class MyEventListener {
#Subscribe
def onStringEvent(event: MyEvent[String]) {
println("String event caught")
}
#Subscribe
def onIntEvent(event: MyEvent[Int]) {
println("Int event caught")
}
}
I can create my com.google.common.eventbus.EventBus, register MyEventListener, and fire an event:
val eventBus = new EventBus
eventBus.register(new MyEventListener)
eventBus.post(new MyEvent[String])
But, as you may have guessed already, both onStringEvent and onIntEvent get called as a result. The issue is that Java's/Scala's type erasure drops off the parameter type at runtime and both subscriptions appear to Guava as event: MyEvent.
Ok, my question:
Due to erasure, using the same Event object for different types of Guava events in this manner wouldn't be possible in Java and isn't possible in Scala. However, Scala proves to have a number of nice ways to circumvent Java's erasure problems. Does anybody see another way to achieve this, perhaps using some Scala wizardry?
The problem is in Guava: it cannot see the type parameter, and so it will not distinguish between the two methods. The only possible solution is to create a new class for each type.
That can be really easy:
class MyEvent[T] protected () { /* Your methods here */ }
class MyEventInt extends MyEvent[Int] {}
class MyEventString extends MyEvent[String] {}
and then whenever you need to do anything in your code, just use MyEvent[Int]. But Guava will require at least this much boilerplate.
Note that I've made the MyEvent[T] constructor protected so you have to instantiate one of the de-generified classes. I'm not sure whether that will work for your use-case; I'll assume so. You can get around that also (with type classes), but it adds more boilerplate.