Play framework with Akka and WS

本文介绍如何在Play框架中设置Akka Actors系统,并利用Play WS模块调用其他微服务。通过创建多个Actors来处理不同的任务,如解析工作内容、管理简历等。同时,演示了如何使用Play WS进行HTTP请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Play framework with Akka and WS

1 Set Up Akka in Playframework
In my controller which I believe it is single, I set up the AKKA system.
package controllers

import actors._
import actors.jobs.{JobServiceActor, JobParseActor}
import actors.resumes.{ResumeServiceActor, ResumeParseActor, ResumeAttachActor}
import akka.actor.Props
import com.sillycat.dao.{IpplyJobDAO, DAO}
import com.sillycat.util.IncludeLogger
import com.wordnik.swagger.annotations._
import models.ScanTriggerRequest
import play.api.libs.concurrent.Akka
import play.api.libs.json.{JsError, Json}
import play.api.mvc.{BodyParsers, Action, Controller}
import play.api.Play.current
import akka.contrib.throttle.TimerBasedThrottler
import akka.contrib.throttle.Throttler._
import scala.concurrent.duration._
import com.wordnik.swagger.annotations._

object ScanTriggerController extends Controller with IncludeLogger with IncludeWSConfig{

implicit val scanTriggerWrites = Json.writes[ScanTriggerRequest]
implicit val scanTriggerReads = Json.reads[ScanTriggerRequest]

Akka.system.actorOf(JobParseActor.props, name = "job-parse-actor")

Akka.system.actorOf(JobServiceActor.props, name = "job-service-actor")

Akka.system.actorOf(ResumeAttachActor.props, name = "resume-attach-actor")

Akka.system.actorOf(ResumeParseActor.props, name = "resume-parse-actor")

Akka.system.actorOf(ResumeServiceActor.props, name = "resume-service-actor")

Akka.system.actorOf(TriggerActor.props, name = "trigger-actor")

val contextIOActor = Akka.system.actorOf(ContextIOActor.props, name = "contextio-actor")

val contextIOThrottler = Akka.system.actorOf(Props(classOf[TimerBasedThrottler], contextio_throttle msgsPer 60.second), name = "conetxt-io-throttler")

contextIOThrottler ! SetTarget(Some(contextIOActor))

def trigger = Action(BodyParsers.parse.json) { request =>
val b = request.body.validate[ScanTriggerRequest]
logger.debug("Processing request with param = " + request.body)
b.fold(
errors => {
BadRequest(Json.obj("status" -> "OK", "message" -> JsError.toJson(errors)))
},
trigger => {
//TODO more validation on the params
logger.debug("Param validation success, param = " + trigger)

val triggerActor = Akka.system.actorSelection("/user/trigger-actor")
logger.debug("Prepare the trigger action = " + triggerActor + ", and fire message!")
triggerActor ! trigger
Ok(Json.obj("status" -> "OK"))
}
)
}

}

In any other actors or any other controllers, we can do as follow:
val jobServiceActor = context.actorSelection("/user/job-service-actor")
jobServiceActor ! JobContentPersistMessage(msg.jobId, jobCity, msg.emailContent)

In my case I have one controller to trigger my actions, maybe in the future I need to set up the AKKA system in global class or some where.

2 WS to call other Micro Service
Here is how I call other micro service
import akka.actor.{Actor, Props}
import com.sillycat.dao.{DAO, IpplyJobDAO, ResumeDAO}
import com.sillycat.util.IncludeLogger
import models.messages.jobs.{JobPersistMessage, JobScanMessage, JobContentParseMessage, JobContentScanMessage}
import models.messages.resumes._
import models.{ResumeScanResponse, ResumeScanAttachmentResponse, JobContentResponse, JobScanResponse}
import play.api.libs.json.Json
import play.api.libs.ws.{WS, WSResponse}
import utils.IncludeRegex
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global

import scala.concurrent.Future
…snip...
case msg:JobContentScanMessage => {
logger.debug("receiving the message JobContentScanMessage" + msg)
//context.io fetch job content, actually it is email content, I need the city and location info
val future:Future[WSResponse] = WS.url(contextio_host + "/jobs/" + msg.accountCode +"/" + msg.messageCode ).get()
//scan jobs success
future onSuccess {
case response if response.status == 200 => {
logger.trace("Scanning job content = " + response.json)

response.json.asOpt[JobContentResponse].map { job =>
logger.trace("Scanning result job content = " + job)
val jobContentParseMessage = JobContentParseMessage(msg.jobId, job.content)
logger.debug("fire the message to job-parse-actor to parse email content.")
jobParseActor ! jobContentParseMessage
}
}
case response => {
//handling error
logger.error("Error handle with status = " + response.status + " message = " + response.body)
}
}
//scan jobs fail
future onFailure {
case t => logger.error("An error has occured: " + t.getMessage)
}
}

For post
val request_data = Json.obj(
"provider" -> "CRAIGSLIST",
"accountCode" -> msg.accountCode,
"dateBefore" -> msg.dateBefore.toString(default_date_time_format),
"dateAfter" -> msg.dateAfter.toString(default_date_time_format),
"limit" -> msg.limit,
"offset" -> msg.offset
)
logger.debug("Send json request parameter = " + request_data)
val future:Future[WSResponse] = WS.url(contextio_host + "/jobs/scan").post(request_data)

References:
https://www.playframework.com/documentation/2.4.3/ScalaWS
https://www.playframework.com/documentation/2.4.3/ScalaAkka

akka system
http://sillycat.iteye.com/blog/1767866
http://sillycat.iteye.com/blog/1768625
http://sillycat.iteye.com/blog/1768626
http://sillycat.iteye.com/blog/2099267
http://sillycat.iteye.com/blog/2100232
http://sillycat.iteye.com/blog/2102694
http://sillycat.iteye.com/blog/2175999
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值