I have this trait
trait NonBlockingGoodness extends DataStore {
import akka.dispatch.{ Future, ExecutionContext }
import akka.util.duration._
import akka.util.Timeout
implicit val ec = ExecutionContext.fromExecutorService(yourExecutorServiceGoesHere)
implicit lazy val timeout = Timeout(5 seconds)
}
I would like to access the ExecutionContext in another trait like such
trait AsyncGoodness extends NonBlockingGoodness {
import akka.dispatch.Future
def doSomething = {
Future { "Future is the bomb." }
}
However, I am getting the error
Could not find implicit value for parameter executor: akka.dispatch.ExecutionContext
UPDATED:
I figured out how to get the ExecutionContext in scope
trait AsyncGoodness extends NonBlockingGoodness {
import akka.dispatch.ExecutionContext
import akka.dispatch.Future
def doSomething()(implicit executor: ExecutionContext) = {
Future { "Future is the bomb." }
}
However, I have a follow-up question. Since I may have more than 1 method in AsyncGoodness that uses ExecutionContext, is there a way to pass it in at the trait level instead of at each method like I did above.
I know you'd rather not have to import anything extra, but something like this should work for you.
trait NonBlockingGoodness {
import scala.concurrent.{ Future, ExecutionContext }
import scala.concurrent.util.duration._
import akka.util.Timeout
object Implicit {
implicit val ec = ExecutionContext.Implicits.global
implicit lazy val timeout = Timeout(5 seconds)
}
}
trait AsyncGoodness extends NonBlockingGoodness {
import scala.concurrent.Future
import Implicit._
def doSomething = {
Future { "Future is the bomb." }
}
}
As it turns out, all I need to do is explicitly specify ec return type for the compiler to use it. Here's the working code
trait NonBlockingGoodness extends DataStore {
import akka.dispatch.{ Future, ExecutionContext }
import akka.util.duration._
import akka.util.Timeout
implicit val ec: ExecutionContext = ExecutionContext.fromExecutorService(yourExecutorServiceGoesHere)
implicit lazy val timeout = Timeout(5 seconds)
}
trait AsyncGoodness extends NonBlockingGoodness {
import akka.dispatch.Future
def doSomething = {
Future { "Future is the bomb." }
}
Related
I have a wrapper trait that extends BasicFormats from spray json https://github.com/spray/spray-json/blob/release/1.3.x/src/main/scala/spray/json/BasicFormats.scala
but I would like to override the behavior of implicit object BigDecimalJsonFormat extends JsonFormat[BigDecimal] to add rounding logic. Example being
import spray.json._
import scala.math.BigDecimal.RoundingMode
case class Foo(i: BigDecimal)
object Foo extends DefaultJsonProtocol {
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] =
new JsonFormat[BigDecimal] {
def write(f: BigDecimal) = JsNumber(f.setScale(2, RoundingMode.HALF_UP))
def read(json: JsValue): BigDecimal =
DefaultJsonProtocol.BigDecimalJsonFormat.read(json)
}
implicit val fooFormatter = jsonFormat1(this.apply)
}
scastie snippet:
https://scastie.scala-lang.org/9RNhajzGRDGMX5QsuAohVA
Great question, I wasn't even aware this may cause so many problems. The solution I am about to propose is probably not the cleanest, but it does the job... First of all, you don't have to extend DefaultJsonProtocol, you might also import it's members:
object Foo {
import DefaultJsonProtocol._
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] = ...
implicit val fooFormatter = jsonFormat1(this.apply)
}
This doesn't solve the problem but that way you can exclude some of the members so that they are not imported. Here's the syntax for that
import DefaultJsonProtocol.{BigDecimalJsonFormat => _, _}
It basically says: don't import BigDecimalJsonFormat but import the rest.
And the following code sums it up.
import spray.json._
import scala.math.BigDecimal.RoundingMode
case class Foo(i: BigDecimal)
object Foo {
import DefaultJsonProtocol.{BigDecimalJsonFormat => _, _}
implicit val roundedBigDecimalProtocol: JsonFormat[BigDecimal] =
new JsonFormat[BigDecimal] {
def write(f: BigDecimal) = JsNumber(f.setScale(2, RoundingMode.HALF_UP))
def read(json: JsValue): BigDecimal =
DefaultJsonProtocol.BigDecimalJsonFormat.read(json)
}
implicit val fooFormatter = jsonFormat1(this.apply)
}
ive come across this problem :
Caused by: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
The app works, but i can only make like 3 or 4 requests and then im getting this error, so whats happening (im guessing) is im creating new connections per request and id like to keep one connection per app lifecycle, any idea how to modify the code to do so?
Tried injecting UsersDao to my controller instead of using it as an object but that changes nothing
Im really new to scala so any help is appreciated
Dao
import config.DatabaseConfig
import domain.{User, UsersTable}
import slick.jdbc.PostgresProfile.api._
import slick.sql.SqlAction
import scala.concurrent.Future
trait BaseDao extends DatabaseConfig {
val usersTable = TableQuery[UsersTable]
protected implicit def executeFromDb[A](action: SqlAction[A, NoStream, _ <: slick.dbio.Effect]): Future[A] = {
println(db)
db.run(action)
}
}
object UsersDao extends BaseDao {
def findAll: Future[Seq[User]] = usersTable.result
def create(user: User): Future[Long] = usersTable.returning(usersTable.map(_.id)) += user
def findByFirstName(firstName: String): Future[Seq[User]] = usersTable.filter(_.firstName === firstName).result
def findById(userId: Long): Future[User] = usersTable.filter(_.id === userId).result.head
def delete(userId: Long): Future[Int] = usersTable.filter(_.id === userId).delete
}
DatabaseConfig
trait DatabaseConfig extends Config {
val driver = slick.jdbc.PostgresProfile
import driver.api._
def db = Database.forConfig("dbname")
implicit val session: Session = db.createSession()
}
Controller
import domain.User
import javax.inject.{Inject, Singleton}
import play.api.libs.json.Json
import play.api.mvc._
import repository.UsersDao
import scala.concurrent.{ExecutionContext, Future}
#Singleton
class UserController #Inject() ()(cc: ControllerComponents, parsers: PlayBodyParsers)(implicit exec: ExecutionContext) extends AbstractController(cc) {
def addUser = Action.async(parse.json[User]) { req => {
UsersDao.create(req.body).map({ user =>
Ok(Json.toJson(user))
})
}
}
I'm trying to make sense of the error(s) I'm seeing below, and to learn how to fix it.
could not find implicit value for parameter materializer: akka.Stream.Materializer
val fut: Future[Result] = action.apply(fakeRequest).run
^
not enough arguments for method run (implicit materializer: akka.stream.Materializer)scala.concurrent.Future[play.api.mvc.Result].
Unspecified value parameter materializer.
val fut: Future[Result] = action.apply(fakeRequest).run
^
Here is the test code that produced the error(s):
package com.foo.test
import com.foo.{Api, BoundingBox}
import org.scalatest.{FlatSpec, Matchers}
import play.api.libs.json._
import play.api.mvc._
import play.api.test.{FakeHeaders, FakeRequest}
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
class TestJmlPlay extends FlatSpec with Matchers {
val bbox = new BoundingBox(-76.778154438007732F, 39.239828198015971F, -76.501003519894326F, 39.354663763993926F)
"latitudes" should "be between swLat and neLat" in {
val action: Action[AnyContent] = (new Api).getForPlay(bbox)
val jsonStr = getStringFromAction(action)
areLatitudesOk(jsonStr, bbox) shouldBe true
}
private def getStringFromAction(action:Action[AnyContent]):String = {
val fakeRequest: Request[String] = new FakeRequest("fakeMethod", "fakeUrl", new FakeHeaders, "fakeBody")
val fut: Future[Result] = action.apply(fakeRequest).run // <== ERROR!
val result = Await.result(fut, 5000 milliseconds)
result.body.toString
}
private def areLatitudesOk(jsonStr: String, bbox: BoundingBox): Boolean = ...
}
You can create an implicit ActorMaterializer within your test class which will use testkit's ActorSystem:
import akka.testkit.TestKit
import akka.actor.ActorSystem
class TestJmlPlay(_system : ActorSystem) extends TestKit(_system) ... {
implicit val materializer: ActorMaterializer = ActorMaterializer()
val bbox = ...
You don't need Materializer.
I believe you are calling not the right action.apply method.
You want def apply(request: Request[A]): Future[Result]
To call the right, you need FakeRequest[AnyContent], same parametrized type as action:Action[AnyContent].This type is forced by PlayBodyParser I believe you set for your action.
After that you don't need .run call
Consider a code below:
import akka.actor.{ActorSystem, Props}
import akka.io.IO
import spray.can.Http
object Main extends App {
implicit val system = ActorSystem()
val handler = system.actorOf(Props[DemoServiceActor], name = "handler")
IO(Http) ! Http.Bind(handler, interface = "localhost", port = 8080)
}
import akka.actor.Actor
import spray.routing.HttpService
class DemoServiceActor extends Actor with DemoService {
def actorRefFactory = context
def receive = runRoute(demoRoute)
}
trait DemoService extends HttpService {
implicit def executionContext = actorRefFactory.dispatcher
def demoRoute = {
path("test") {
get {
println("ping")
complete("test complete")
}
}
}
}
When main runs it print to console ping. Why? How to fix this?
I would like to have an implicit ExecutionContext passed to a partially implemented trait.
In code example:
import scala.concurrent.Future
trait Processor[T,R] {
def process(op:T): Future[R] = {
//Do something to get stuff from abstract methods
Future {
//Do something that returns type R
}
}
}
This will ask for an ExecutionContext, so I have changed the declaration to:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
trait Processor[T,R] {
def process(op:T)(implicit executor: ExecutionContext): Future[R] = {
//Do something to get stuff from abstract methods
Future {
//Do something that returns type R
}
}
}
But then when I try to extend the trait like this:
import scala.concurrent.ExecutionContext.Implicits.global
class StringProcessor extends Processor[String,String] {
//Bla bla bla
}
The compiler tells me that the method process is not implemented an my class should be abstract.
How can I ensure that my construct works without having to put an implicit val xc:ExecutionContext in the declaration of the trait?
I don't seem to be having any issues with the following code, which is similar to your code but provides a full implementation. Not sure what the issue is.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
trait Processor[T,R] {
def process(op:T)(implicit executor: ExecutionContext): Future[R] = {
//Do something to get stuff from abstract methods
Future {
getR
}
}
def getR:R
}
class StringProcessor extends Processor[String,String] {
def getR = "foo"
}