- Create a Scala file, say CustomMailbox.scala, in package com.packt.chapter1.
Add the following required imports to the top of the file:
import java.util.concurrent.ConcurrentLinkedQueue
import akka.actor.{Props, Actor,
ActorSystem,ActorRef}
import akka.dispatch.{ MailboxType,
ProducesMessageQueue,
Envelope, MessageQueue}
import com.typesafe.config.Config
- Define a MyMessageQueue, which extends trait MessageQueue and implementing methods:
class MyMessageQueue extends MessageQueue {
private final val queue = new
ConcurrentLinkedQueue[Envelope]()
// these should be implemented; queue used as example
def enqueue(receiver: ActorRef, handle: Envelope): Unit =
{
if(handle.sender.path.name == "MyActor") {
handle.sender ! "Hey dude, How are you?, I Know your
name,processing your request"
queue.offer(handle)
}
else handle.sender ! "I don't talk to strangers, I
can't process your request"
}
def dequeue(): Envelope = queue.poll
def numberOfMessages: Int = queue.size
def hasMessages: Boolean = !queue.isEmpty
def cleanUp(owner: ActorRef, deadLetters: MessageQueue) {
while (hasMessages) {
deadLetters.enqueue(owner, dequeue())
}
}
}
- Let's provide a custom mailbox implementation, which uses the preceding MessageQueue:
class MyUnboundedMailbox extends MailboxType
with ProducesMessageQueue[MyMessageQueue] {
def this(settings: ActorSystem.Settings,
config: Config) = { this()
}
// The create method is called to create the MessageQueue
final override def create(owner: Option[ActorRef], system::
Option[ActorSystem]):MessageQueue = new MyMessageQueue()
}
- Create an application.conf file and put the below configuration. An application.conf file is used to configure Akka application properties and it resides in the project's resource directory.
custom-dispatcher {
mailbox-requirement =
"com.packt.chapter1.MyMessageQueue"
}
akka.actor.mailbox.requirements {
"com.packt.chapter1.MyMessageQueue" = custom-dispatcher-
mailbox
}
custom-dispatcher-mailbox {
mailbox-type = "com.packt.chapter1.MyUnboundedMailbox"
}
- Now define an actor that would use the preceding configuration, say, MySpecialActor. It's special, because it would talk to the actor whom it knows, and say hello to that actor only:
class MySpecialActor extends Actor {
override def receive: Receive = {
case msg: String => println(s"msg is $msg" )
}
}
- Define an actor who will try to talk to the special actor:
class MyActor extends Actor {
override def receive: Receive = {
case (msg: String, actorRef: ActorRef) => actorRef !
msg
case msg => println(msg)
}
}
- Create a test application, CustomMailbox, as follows:
object CustomMailbox extends App {
val actorSystem = ActorSystem("HelloAkka")
val actor =
actorSystem.actorOf(Props[MySpecialActor].withDispatcher
("custom-dispatcher"))
val actor1 = actorSystem.actorOf(Props[MyActor],"xyz")
val actor2 =
actorSystem.actorOf(Props[MyActor],"MyActor")
actor1 ! ("hello", actor)
actor2 ! ("hello", actor)
}
- Run the application in the IDE or from the console, and you will get the following output:
I don't talk to strangers, I can't process your request
Hey dude, How are you?, I Know your name,processing your request
msg is hello