When defining a class where I need to load my Akka implicits from Main I do like this:
class Example()(implicit system: ActorSystem, materializer: ActorMaterializer)
However I wish to do the exact same thing using an object, is there a way to do this?
Related
given a class
class Foo #Inject()(cfg: Config, private val emr: AmazonElasticMapReduce = AmazonElasticMapReduceClientBuilder.defaultClient())
(implicit actorSystem: ActorSystem, ec: ExecutionContext)
play framework fails when it tries to Inject the 'emr' value.
I don't want play to inject it, instead I want to use the default value.
Is it possible to define?
You need to add to your Module.scala:
bind(classOf[AmazonElasticMapReduce]).toInstance(AmazonElasticMapReduceClientBuilder.defaultClient()).asEagerSingleton()
Instead of trying to provide it to the constructor.
If you don't want it injected at all, you can have it just as a member in the class.
I was trying to look into trait and object in scala when it seems like we can use trait and object to do a similar task.
What should be the guiding principles on when to use trait and when to use object?
Edit:
As many of you are asking for an example
object PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
trait PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
There is a Process class which can use the object
object Process {
def doSomething(df: DataFrame): DataFrame {
PercentileStats.addPercentile(df)
}
}
We can also make it use the trait
object Process with PercentileStats {
def doSomething(df: DataFrame): DataFrame {
addPercentile(df)
}
}
I think the real question here is Where do I put stand-alone functions?
There are three options.
In the package
You can put stand-alone functions in the outer package scope. This makes them immediately available to the whole package but the name has to be meaningful across the whole package.
def addPercentile(df: DataFrame): DataFrame // implementation
In an object
You can group stand-alone functions in an object to provide a simple namespace. This means that you have to use the name of the object to access the functions, but it keeps them out of the global namespace and allows the names to be simpler:
object PercentileStats {
def add(df: DataFrame): DataFrame // implementation
}
In a trait
You can group stand-alone functions in a trait. This also removes them from the package namespace, but allows them to be accessed without a qualifier from classes that have that trait. But this also makes the method visible outside the class, and allows them to be overridden. To avoid this you should mark them protected final:
trait PercentileStats {
protected final def addPercentile(df: DataFrame): DataFrame // implementation
}
Which is best?
The choice really depends on how the function will be used. If a function is only to be used in a particular scope then it might make sense to put it in a trait, otherwise the other options are better. If there are a number of related function then grouping them in an object makes sense. One-off functions for general use can just go in the package.
Object - is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.
As a top-level value, an object is a singleton.
Traits - are used to share interfaces and fields between classes.
Classes and objects can extend while traits cannot be instantiated and therefore have no parameters.
So, it means that if you prefer singleton type implementation with no new instance happen then use Object but if you want to inherit implementation to other class or objects then you can use trait.
Traits: are equivalent to interfaces in Java. So you can use it to define public contracts like interfaces in Java. In addition, a trait can be used to share values (beside methods) between classes extends the trait.
Objects in Scala is actually quite flexible. Example use cases include:
singletons: If you think that your objects are singletons (exactly
one instance exists in the program), you can use object.
factory: for instance, companion object of a class can be used as factory for creating instances of the class.
to share static methods: for example, common utilities can be declared in one object.
You also have to consider how you would want to use / import it.
trait Foo {
def test(): String
}
object Bar extends Foo
import Bar._
Objects enable you to import rather than mix in your class.
It is a life saver when you want to mock - with scalamock - a class that mixes a lot of traits and expose more than 22 methods that you don't really need exposed in the scope.
I'm currently baking my first cake pattern, so please bear with me.
I took my working monolithic app and I cutted it into functional layers. The cut looks clean but resulted in two of the layers that depend on an implicit ActorSystem.
I tried to solve this dependency like this:
trait LayerA {
this: ActorSystemProvider =>
private implicit val implicitActorSystem = actorSystem
import implicitActorSystem.dispatcher // implicit execution ctx
...
}
... and similarly for LayerX
My assembly class looks like:
class Assembly extends LayerA with LayerB with LayerX with ActorSystemProvider
where ActorSystemProvider simply instantiates the actor system.
This does not work given that the ActorSystem does not exist when the dependencies are resolved and the val's are instantiated, resulting in a NPE. This also looks really ugly and I'm sure there has to be a nicer/easier way to deal with it.
How should I deal with shared implicit dependencies among layers when using the cake pattern, like ActorSystem in this case?
Thanks
Self types is not a requirement for building a caked architecture, actually i use self types only in cases when a trait is a component of a layer. So when i need to place some implicit into the scope (for example ActorRefFactory for Spray Client) i just mix a trait in :
trait ActorSystemProvider {
implicit def actorSystem: ActorSystem
}
And on the lowest layer (so called "end of the world") i have the following code structure:
trait ServiceStack
extends SomeModule
with SomeModule2
with SomeModule3
with ActorSystemProvider
object ServiceLauncher extends App with ServiceStack {
val actorSystem = ActorSystem("ServiceName")
}
It's an oversimplified example (if you want a great example of a real system build on top of a Cake Pattern then you should definitely take a look at the Precog system, example where different modules/layers connects), but not you can mix implicit ActorSystem when you need it.
If you can instantiate the vals lazily rather than eagerly, you can make the implicitActorSystem a lazy val instead of a val. So it only gets executed when it is accessed the first time. I think this should solve the problem of NPE.
(Another little known interesting fact posted by #ViktorKlang FYI: If the initialization of a lazy val throws an exception, it will attempt to reinitialize the val at next access.)
Another way would be to make each of your methods which need execution context accept an implicit executionContext like:
trait LayerA {
def getUser(id: Int)(implicit ec: ExecutionContext) = {
...
}
}
When i run base example for testing actors:
class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender
with WordSpec with MustMatchers with BeforeAndAfterAll {
I got error:
class WordSpec needs to be a trait to be mixed in
what am I doing wrong?
In ScalaTest 2.0 you can find both class and trait for WordSpec. The class named WordSpec and trait is WordSpecLike. So just use WordSpecLike instead of WordSpec:
class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender
with WordSpecLike with MustMatchers with BeforeAndAfterAll {
In addition to what 1esha proposed, there's one more solution in akka documentation
If for some reason it is a problem to inherit from TestKit due to it being a concrete class instead of a trait, there’s TestKitBase:
import akka.testkit.TestKitBase
class MyTest extends TestKitBase {
implicit lazy val system = ActorSystem()
// put your test code here ...
shutdown(system)
}
The implicit lazy val system must be declared exactly like that (you can of course pass arguments to the actor system factory as needed) because trait TestKitBase needs the system during its construction.
As of Scalatest 2.0, the Specs you mix in are now classes not traits. Which means you can't use them with Akka's test kit... both are classes and you can only extend one of them.
Switch to scalatest 1.9.1. It's still supported by them and is the last version that released before they made that change and broke things for akka users. In 1.9.1, the specs are still traits.
Say I have:
import org.scalatest.ShouldMatchers._;
This brings a few implicit conversions into scope.
How can I alias them in a package object so that I can bring the implicits into scope with:
import code.ThePackageObject._;
Apparently the ShouldMatchers object extends the ShouldMatchers trait (where the actual definition of the implicits are done). This is a common idiom that allows to simply mix the trait where you need it. So you can simply mix ShouldMatchers (the trait) in your package object:
package object ThePackageObject extends ShouldMatchers