Robert F
Robert F

Reputation: 451

How to use a @Singleton from an Akka actor?

I am new to Dependency Injection and now when I migrated my application to Play 2.5.x I need to learn.

I have a singleton service looking something like this:

import javax.inject._
@Singleton
class WorkerService {
   def doWork(work:String) {
      ...
   }
}

I have an actor looking something like this:

import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
import akka.actor._
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import scalaj.http._

import WorkerService

object PollActor {
  def props(host: String) = Props(new PollActionActor(host))
}

// Actor that polls a host for information
class PollActor(host: String) extends Actor with ActorLogging {
    // timer for poll
    var timer: Cancellable = context.system.scheduler.schedule(0 second, 10 second, self, TimeStep())

    // handle messages
    override def receive = {
        case TimeStep() =>
            getWork match {
                case Some(work:String) =>
                    // How to do this?: ChecklistService.doWork(work)
                case None =>
            }
    }

    def getWork = {
        try {
            Some(Http(host)
                    .option(HttpOptions.readTimeout(10000))
                    .option(HttpOptions.connTimeout(10000))
                    .asString.body)
        } catch {
          case _:Throwable =>
            None
        }
    }

    case class TimeStep()
}

And a controller something like this:

@Singleton
class Application @Inject() (implicit system: ActorSystem) extends Controller {
    val pollActor = system.actorOf(PollActor.props("127.0.0.1"))

    def index = Action {
        pollActor ! TimeStep
    }
}

How can I call WorkerService.doWork in the time step of the actor?

Upvotes: 1

Views: 626

Answers (1)

Bruce Lowe
Bruce Lowe

Reputation: 6213

You probably should not create the actor in the Application class.

Try using a module to create your actor like this

class ApplicationConfigModule extends AbstractModule with AkkaGuiceSupport {

  override def configure(): Unit = {
    bindActor[PollActor]("poll-actor")
  }
}

in your resources/application.conf put this

play.modules.enabled += "com.nowtv.platform.search.module.ApplicationConfigModule"

Then inject the service into your actor

class PollActor @Inject()(WorkerService: workerService) extends Actor 

And inject the Actor into your Controller so you can use it there

@Singleton
class Application @Inject() (@Named("poll-actor") pollActor: ActorRef) extends Controller {

Upvotes: 1

Related Questions