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
}
Related
I'm trying to figure out how to get traditional constructor-based dependency injection to work with type class patterns.
For example, given
trait MyTypeClass[A] {
def doSomething(a: A): Unit
}
class TypeClasses(prefix: String) {
implicit val stringTC = new MyTypeClass[String] {
def doSomething(a: String) = println(s"$prefix a")
}
implicit val intTc = new MyTypeClass[Int] {
def doSomething(a: Int) = println(s"s$prefix $a")
}
}
class MyLogic {
def doSomething[A](a: A)(implicit myTypeClass: MyTypeClass[A]) = myTypeClass.doSomething(a)
doSomething("Hello world")
}
What would be the best way to get the implicit type class instances inside an instance of TypeClasses into MyLogic?
The only things I've come up with are to either
a) Inject an instance of TypeClasses into MyLogic in the constructor, and then import instanceOfTypeClasses._. However this has the downside that it has to be repeated every class, and subclasses can't inherit the import.
or b) make TypeClasses a trait, prefix a def, and have MyLogic extend TypeClasses and then dependency inject an instance for prefix in the constructor. However this becomes messy as it's allowing the dependencies for TypeClasses to bleed into MyLogic.
In case you need dependency injection, as I may assume from your tags, you may try to use distage (slides) DI framework for Scala (disclaimer: I'm the author).
It supports typeclass instance injection.
Because your typeclass instances are created dynamically in the TypeClasses class,
you have to add a TypeClasses constructor parameter in every class that needs
to call a function that requires a typeclass instance.
But, you can remove the import typeclasses._ boilerplate by creating implicit
defs that would extract the instances from the TypeClasses object when it's available as an implicit:
trait MyTypeClass[A] {
def doSomething(a: A): Unit
}
object MyTypeClass {
implicit def intFromTypeClasses(implicit typeClasses: TypeClasses): MyTypeClass[Int] = typeClasses.intTc
implicit def stringFromTypeClasses(implicit typeClasses: TypeClasses): MyTypeClass[String] = typeClasses.stringTC
}
Because the implicit defs are defined in the companion object for MyTypeClass they will always be available without any imports.
Then you should add TypeClasses as an implicit parameter in MyLogic, this would make it available for implicit defs to extract instances from:
class MyLogic(implicit typeClasses: TypeClasses) {
def doSomething[A](a: A)(implicit myTypeClass: MyTypeClass[A]) = myTypeClass.doSomething(a)
doSomething("Hello world")
// same as doSomething("Hello world")(MyTypeClass.stringFromTypeClasses(typeClasses))
}
Then, in distage, declare the following bindings
import distage._
class MyAppModule extends ModuleDef {
make[String].from("myprefix")
make[TypeClasses]
make[MyLogic]
}
And everything is wired:
val ctx: Locator = Injector().produce(new MyAppModule)
implicit val typeClasses = ctx.get[TypeClasses]
ctx.get[MyLogic].doSomething("Hello world")
So I have this simple Scala trait with a method that requires a type parameter specified.
The DAO class extends the trait and uses the trait's method. Even if I do not provide a concrete type to the method, the code still compiles, and I suppose this is achieved by Scala auto inferring the generic type (guessing what the type value should be)? Is it right?
And also how does Scala infer types in situations like this in general?
Thanks a lot!!
class DAO #Inject()(val configProvider: DatabaseConfigProvider) extends
ManagementAppDatabase {
private val users = TableQuery[UserTable]
def findUserByEmail(email: String): Future[Option[User]] = {
execute(users.filter(_.email === email).result.headOption)
}
}
trait ManagementAppDatabase {
val configProvider: DatabaseConfigProvider
def execute[T](dBIO:DBIO[T]): Future[T] = configProvider.get[JdbcProfile].db.run(dBIO)
}
It's not a guess, the compiler can infer the type in this case as the object passed to the method has the type defined:
def execute[T](dBIO:DBIO[T]): Future[T] = configProvider.get[JdbcProfile].db.run(dBIO)
So if you pass a type DBIO[Int], the compiler can fill in the rest:
def execute[Int](dBIO:DBIO[Int]): Future[Int] = configProvider.get[JdbcProfile].db.run(dBIO)
I've a trait:
trait Crawler {
implicit def system: ActorSystem
implicit def executionContext: ExecutionContext
implicit def materializer: Materializer
// other methods
}
And a test class:
class CrawlerSpec extends AsyncFlatSpec with Matchers with Crawler {
override implicit val system: ActorSystem = ActorSystem("ufo-sightings")
override implicit val executionContext: ExecutionContext = implicitly[ExecutionContext]
override implicit val materializer: Materializer = ActorMaterializer()
// test
}
According to Scalatest doc:
Asynchronous style traits extend AsyncTestSuite, which provides an
implicit scala.concurrent.ExecutionContext named executionContext.
But the test blows up with a NPE due to the ExecutionContext being null (should fail gracefully, but that's another matter).
java.lang.NullPointerException was thrown.
java.lang.NullPointerException
at scala.concurrent.impl.Future$.apply(Future.scala:31)
at scala.concurrent.Future$.apply(Future.scala:494)
Why isn't the implicit ExecutionContext picked up?
<rant>
Implicit resolution is a nightmare. At the expense of saving a few
keystrokes, it makes code so fragile that removal of a single
import breaks it. There's a reason other statically typed languages like
Haskell or Kotlin don't have it; it's a stinking mess.
</rant>
Let's see what happens here:
trait A {
implicit def executionContext: ExecutionContext
}
you declare here that A would provide implicit value. Then
class B extends A {
override implicit val executionContext: ExecutionContext = implicitly[ExecutionContext]
}
So what does happen here?
value executionContext is initialized during B construction.
then implicitly tries to find a value with ExecutionContext type.
it finds such value: executionContext.
So effectively you did something like:
class B extends A {
val executionContext: ExecutionContext = executionContext
}
You created circular dependency on initialization: you are initializing value with itself. So you take a value though a "getter" returning a property that is still null (as it is just being initialized).
I agree, that implicits are concepts are something that requires a lot of effort, though I would not antagonize them as much as you. Here you had a problem with circular dependency on initialization. It cannot fail gracefully, anything other than Exception would put the program into invalid state.
Solution would be initializing you implicit value without the usage of implicitly. Just put some value there by hand. Or don't use that trait and import implicit from somewhere else.
I have some problem calling my Scala code from Java.
Here is my Scala Class:
case class Foobar(foo: String) extends FoobarParent
object Foobar {
implicit object Format extends Format[Foobar] {
def writes(Foobar: foobar): JsValue = {
....
}
implicit def reads(json: JsValue): JsResult[Foobar] = {
...
}
}
}
Now when I have a method with the following signature:
def publish[T <: FoobarParent](foobarParent: T)(implicit writes: Writes[T]): Unit = {...}
This works fine when calling from Scala code, I simply just do publish[Foobar] (Foobar(...))
However in Java, the signature looks likes this in my IDE:
publish (T FoobarParent, Writes<T> writes)
Now my question is what/how do I fulfil those two parameters in Java?
You usually can get an object's instance like this: Foobar$.MODULE$
and the nested one like this: Foobar.Format$.MODULE$
There's a problem with the companion object here though, because it gets compiled as a different class. It will create a class named Foobar$ which is not of the type Foobar nor does it extends FoobarParent. So you can't just call publish(Foobar$.MODULE$, Foobar.Format$.MODULE$);. I think you'll just have to create a new instance:
publish(new Foobar("..."), Foobar.Format$.MODULE$);
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!