On the akka website, you can the following definition:
sealed trait AccountCommand[Reply] extends ExpectingReply[Reply]
final case class Withdraw(amount: BigDecimal)(override val replyTo: ActorRef[OperationResult])
extends AccountCommand[OperationResult]
How to assign an ActorRef to replyTo?
I've taken the code as an example and try to implement on own type:
case object Channel (override val replyTo: ActorRef[SendMessage])
extends ExpectingReply[SendMessage]
and the compiler complains.
The way, that the compiler does not complain:
case object Channel extends ExpectingReply[SendMessage] {
override def replyTo: ActorRef[SendMessage] = ???
}
Is the example on akka website wrong?
If your message does not have fields, you can use a case class without parameters:
case class Channel()(override val replyTo: ActorRef[SendMessage])
extends ExpectingReply[SendMessage]
If you're asking about how to create an instance of such a class, then you should use the standard multi-parameter function call syntax:
val msg = Channel()(sendMessageActorRef)
That being said, it looks to me that specifically in that part of the Akka API that you linked to, you don't have to explicitly provide any ActorRefs, Effects seem to do it kind of automatically.
Related
Suppose I have two classes, Person and Business, that are extended by the trait Entity.
trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity
Assuming I cannot change Entity, Person and Business (they are in a different file and not to be changed) how can I define a function, say a printEntity, that prints the field name or id, depending on the entity? For example, given instances of Person and Business, how can I do something like this:
object Main extends App {
val person1: Person = Person("Aaaa Bbbb")
val business1: Business = Business("0001")
// How can I do something like this?
person1.printEntity // would call a function that executes println(id)
business1.printEntity // would call a function that executes println(name)
}
Any ideas are appreciated! Sorry for the lack of context, I am still learning!
This is done via so called "extension methods". In scala 2 this is achieved using implicit wrapper class:
trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity
implicit class PersonWrapper(val p: Person) extends AnyVal {
def printEntity(): Unit = {
println(p.name)
}
}
implicit class BusinessWrapper(val b: Business) extends AnyVal {
def printEntity(): Unit = {
println(b.id)
}
}
val person1: Person = Person("Aaaa Bbbb")
val business1: Business = Business("0001")
person1.printEntity()
business1.printEntity()
// prints:
//Aaaa Bbbb
//0001
Note, x.printEntity can be called without parentheses, but, by convention, methods with Unit result type and side effects should be called with explicit empty parentheses.
UPD: As #DmytroMitin pointed out, you should extend implicit wrapper classes from AnyVal. This allows the compiler to avoid actually allocating wrapper class instances at runtime, improving performance.
I have a scenario where I need to provide a Behavior of a specific type. This Behavior also needs to handle events that are published on the Event Stream. So say the specific type is:
case class DoSomething(i: Int)
and I then need to implement a function to return a Behavior to handle this type of message:
def foo(): Behavior[DoSomething]
I then also need to handle the following message on the event stream:
case class PublishedEvent(str: String)
The only solution I came up with was to spawn another actor from within my DoSomething behavior and then forward messages to it:
sealed trait Command
case class Command1(str: String) extends Command
case class Command2(str: String) extends Command
def foo(): Behavior[DoSomething] = Behaviors.setup { context =>
val actor = context.spawnAnonymous[Command](Behaviors.setup { context =>
context.system.eventStream ! EventStream.Subscribe(context.messageAdapter {
case PublishedEvent(str) => Command2(str)
})
Behaviors.receiveMessage {
case Command1(str) =>
println("Received Command1: " + str)
Behaviors.same
case Command2(str) =>
println("Received Command1: " + str)
Behaviors.same
}
})
Behaviors.receiveMessage {
case DoSomething(i) =>
actor ! Command1(i.toString)
Behaviors.same
}
}
My question is is there any means of avoiding spawning a new actor and doing it all from within the same actor? i.e. Is there a way I can map a Behavior[Command] to a Behavior[DoSomething]?
I also have this problem regularly and the best solution I found is to use the narrow[...] method on a common "super Behavior" to narrow down on a message type a client is supposed to send to the respective actor. It is possible to combine the handling of both message types in one Behavior by defining a common interface (in scala of course a trait):
sealed trait CommandOrDoSomething // #TODO find better name
final case class DoSomething(i:Int) extends CommandOrDoSomething
sealed trait Command extends CommandOrDoSomething
case class Command1(str: String) extends Command
case class Command2(str: String) extends Command
def getBehavior(): Behavior[CommandOrDoSomething] = Behaviors.setup { context =>
Behaviors.receiveMessage {
// handle all kinds of messages here
}
}
Now, if you want to pass a Behavior[DoSomething] to a client, you can simply obtain it like this:
def foo(): Behavior[DoSomething] = getBehavior().narrow[DoSomething]
You can keep the Command trait private to your current context, but I think you will have to expose at least the common super trait to the outside world. With union types as they will be available in Scala 3 this can be avoided and you won't need the artificial super trait.
The docs (as well as the signature) indicate that transformMessages on Behavior would work, provided that the externally sent messages map 1:1 to internal messages:
def transformMessages[Outer: ClassTag](matcher: PartialFunction[Outer, T]): Behavior[Outer]
i.e. an actor materialized with Behavior[T].transformMessages[Outer] { ??? } will yield an ActorRef[Outer]
sealed trait External
case class DoSomething(i: Int) extends External
private sealed trait Internal
private case class Command1(str: String) extends Internal
private case class Command2(str: String) extends Internal
private def internalBehavior: Behavior[Internal] = Behaviors.setup { context =>
// do stuff with context
Behaviors.receiveMessage {
case Command1(s) => ???
case Command2(s) => ???
}
}
import akka.actor.typed.Behavior.BehaviorDecorators
def externalBehavior: Behavior[External] =
internalBehavior.transformMessages {
case DoSomething(i) => Command1(i.toString)
}
In this case, the internal commands are invisible outside of their scope. The main potential drawback I see (beyond the slight ickiness of bringing a PartialFunction into typed) is that within an actor with Behavior[Internal], you can't get the ActorRef for actor's external "personality", unless you have something crazy like
case class DoSomething(i: Int, recipient: ActorRef[External]) extends External
private case class Command1(str: String, externalPersonality: ActorRef[External]) extends Internal
It's worth noting that in the case where the internal messages are under your control, the 1:1 restriction can be worked around.
I am reading the source code of Spark. I see it seems a class extends itself.
My questions: does it extend itself? If so, what's it called? Why do we do that?
class OneHotEncoderModel private[ml] (
#Since("2.3.0") override val uid: String,
#Since("2.3.0") val categorySizes: Array[Int])
extends Model[OneHotEncoderModel] with OneHotEncoderBase with MLWritable
It's not extending itself. Actually, "extends itself" has no meaning, or one could say all classes extends them-selves.
OneHotEncoderModel(...) extends Model[OneHotEncoderModel] with ...
means that OneHotEncoderModel extends Model. And Model is type-parametrized with OneHotEncoderModel. This construct allows Model to have the actual implementing class as a type-parameter and use it.
This can be used, for example, in an abstract api:
trait Model[A]{
def join(other: A): A
}
Here, to be a Model sub-class, OneHotEncoderModel will have to implement def join(other: OneHotEncoderModel): OneHotEncoderModel
I'm trying to convert JSON from Ajax request to Case class in Scala.js using scala-json https://github.com/MediaMath/scala-json
Here is my classes:
sealed trait Result
sealed trait Error extends Result
sealed trait Msg extends Result
case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
Here is how I'm trying to convert:
import json._
implicit val msgDataAcc = ObjectAccessor.create[MsgData]
implicit val commentErrorAcc = ObjectAccessor.create[CommentError]
println("here2")
val errors = JValue.fromString(req.responseText).toObject[CommentError]
println("here3")
This code just silently dies on string with conversion and "here3" never printed to console.
Here is my JSON from server:
{"obj.comment":[{"msg":["error.minLength"],"args":[10]}],"obj.name":[{"msg":["error.path.missing"],"args":[]}]}
What I'm doing wrong? How to fix this?
So I'm guessing this is scala-js. Any exceptions that happen at the top level (entry point) of a scala-js application aren't always echoed out correctly (depending on environment/browser), if you wrap the whole thing in a Try and print out the stack trace during the catch, you should successfully see exception being thrown.
Main issue above is that you need to define 'accessors' for the case classes. There's 2 ways of doing this, one works out of the box by adding an implicit for each type, the other way requires macro-paradise and gives you a much simpler way of defining accessors for case classes.
Here is the normal non-macro-paradise way:
case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
object MsgData {
implicit val acc = ObjectAccessor.create[MsgData]
}
case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
object CommentError {
implicit val acc = ObjectAccessor.create[CommentError]
}
The implicits can be placed anywhere (following the general rule for scala implicits). Placing them in the companion object is the best way to guarantee the implicit can be found anywhere, without special imports or anything needed.
This is 'less magical' than other libs like circe that use shapeless to automatically derive factories, sometimes in a bloated way. scala-json aims to keep the accessor visible for extension purposes, but this does lead to some explicit boilerplate.
This can be reduced down using macro-paradise:
#accessor case class MsgData(msg: Seq[String], args: Seq[Int]) extends Msg
#accessor case class CommentError(#name("obj.comment") comment: Seq[MsgData]) extends Error
This does the exact same thing as the above code, we just leverage macro-paradise to add the implicit 'acc' field to the companion object automatically.
I am wanting to test one of my akka actors, it uses slick to get the information from the database. In my actor I have this bit of code
CardStationPermissions.retrieveByStationID(stationID).foreach(card => {
I want to know how can I mock that function to change the output instead of relaying on whats in the database?
It's really difficult to mock things that are being called in a static way (in this case, a call on an object as opposed to an instance of a class). When you need to be able to mock and test things like this, I tend to agree with Mustafa's suggestion that creating a trait to represent the relevant methods to mock. A simple example would look as follows:
case class MyObject(id:Long)
trait MyDao{
def getData(input:String):List[MyObject] = ...
}
object MyDao extends MyDao
class MyActor extends Actor{
val myDao:MyDao = MyDao
def receive = {
case param:String => sender ! myDao.getData(param)
}
}
Here you can see that I have a trait to represent my dao methods (only 1 for this example) and then I mix that trait into a scala object as the default instantiation of that trait. When I setup my dao in my actor, I explicitly type it to the trait so that I can substitute a mock impl of that trait later.
So then if I wanted a simple test showing mocking, it could look something like this (via specs2):
class MyActorTest(_system:ActorSystem) extends TestKit(_system)
with Specification with Mockito with ImplicitSender{
def this() = this(ActorSystem("test"))
trait scoping extends Scope{
val mockDao = mock[MyDao]
val actor = TestActorRef(new MyActor{
override val myDao = mockDao
})
}
"A request to get data" should{
"pass the input to the dao and return the result to the sender" in new scoping{
mockDao.getData("foo") returns List(MyObject(1))
actor ! "foo"
expectMsg(List(MyObject(1)))
}
}
}