I recently started developing an Application in Play Scala. Although I have used Play Java for several applications already, I am also new to Scala and Play Scala.
I use DAO pattern to abstract the database interaction. The DAO contains methods for insert, update delete. After reading async and thread-pool related documentation, I figured that making database interaction async was highly important, unless you tweak the Play default thread pool to have many threads.
To ensure that all database calls are handled asynchronously, I made all the call to return a Future instead of a value directly. I have created a separate execution context for the database interactions.
trait Dao[K, V] {
def findById(id: K): Future[Option[V]]
def update(v: V): Future[Boolean]
[...]
}
This has lead to very complex and deeply nested code in actions.
trait UserDao extends Dao[Long, User] {
def existsWithEmail(email: String): Future[Boolean]
def insert(u: User) Future[Boolean]
}
object UserController extends Controller {
def register = Action {
[...]
userDao.existsWithEmail(email).flatMap { exists =>
exits match {
case true =>
userDao.insert(new User("foo", "bar")).map { created =>
created match {
case true => Ok("Created!")
case false => BadRequest("Failed creation")
}
}
case false =>
Future(BadRequest("User exists with same email"))
}
}
}
}
Above is a sample of simplest of actions. Level of nesting gets deeper as I have more database calls involved. Although I figured that some of the nesting can be reduced with the use of for comprehension, I am doubting if my approach itself is fundamentally wrong?
Consider a case where I need to create a user,
a. If none exists already with same email address.
b. If none exists already with same mobile number.
I can create two futures,
f(a) checking if user exists with email.
f(b) checking if user exists with mobile.
I cannot go and insert a new user unless I verify that both conditions evaluate false. I can actually have f(a) and f(b) running in parallel. The parallel execution maybe undesirable in case f(a) evaluates to true, and may work in favor otherwise. Step 3 of creating user depends on both these futures, so I wonder if following is equally good?
trait UserDao extends Dao[Long, User] {
def existsWithEmail(email: String): Boolean
def existsWithMobile(mobile: String): Boolean
def insert(u: User): Unit
}
def register = Action {
implicit val dbExecutionContext = myconcurrent.Context.dbExceutionContext
Future {
if (!userDao.existsWithEmail(email) && !userDao.existsWithMobile(mobile) {
userDao.insert(new User("foo", "bar")
Ok("Created!")
} else {
BadRequest("Already exists!")
}
}
}
Which one is a better approach? Does the approach of using a single Future with multiple calls to database have any downside?
You are correct when you say that a for comprehension can make for less nesting.
To solve the dual-future problem, consider:
existsWithEmail(email).zip(existsWithMobile(mobile)) map {
case (false, false) => // create user
case _ => // already exists
}
If you have a lot of these, you can use Future.sequence( Seq(future1, future2, ...) ) to turn a sequence of futures into a future sequence.
You may want to take a look at more functional idioms for DB access than DAO, e.g., Slick or Anorm. Usually those will compose better and end up being more flexible than DAO.
A side note: it is more efficient to use if/else for a simple true/false test than it is to use match/case, and is the preferred style.
I solved this problem using for comprehension in scala. I added a few implicit type converters to help with error handling.
Initially I did something like,
def someAction = Action.async {
val result =
for {
student <- studentDao.findById(studentId)
if (student.isDefined)
parent <- parentDao.findById(student.get.parentId)
if (parent.isDefined)
address <- addressDao.findById(parent.get.addressId)
if (address.isDefined)
} yield {
// business logic
}
result fallbackTo Future.successful(BadRequest("Something went wrong"))
}
This is how the code was initially structured to counter the dependency between futures. Note that each subsequent future depends on the previous future. Also, each findById is returning a Future[Option[T]] so if within for comprehension is required to handle cases where the methods return None. I used fallbackTo method on the Future to fallback to a BadRequest result if any of the futures evaluated to None (In event of any if condition failing within for comprehension, it returns a failed future) Another issue with above approach was that it would suppress any kind of exception encountered (even exceptions as trivial as NPE) and simply fallback to BadRequest instead, which was very bad.
Above method was able to counter future of options and handle the failed cases, although it was not helpful to figure out exactly which of the futures in the for comprehension had failed. To overcome this limitation, I used implicit type converters.
object FutureUtils {
class FutureProcessingException(msg: String) extends Exception(msg)
class MissingOptionValueException(msg: String) extends FutureProcessingException(msg)
protected final class OptionFutureToOptionValueFuture[T](f: Future[Option[T]]) {
def whenUndefined(error: String)(implicit context: ExecutionContext): Future[T] = {
f.map { value =>
if (value.isDefined) value.get else throw new MissingOptionValueException(error)
}
}
}
import scala.language.implicitConversions
implicit def optionFutureToValueFutureConverter[T](f: Future[Option[T]]) = new OptionFutureToOptionValueFuture(f)
}
The above implicit conversions allowed me to write readable for comprehensions chaining multiple futures.
import FutureUtils._
def someAction = Action.async {
val result =
for {
student <- studentDao.findById(studentId) whenUndefined "Invalid student id"
parent <- parentDao.findById(student.get.parentId) whenUndefined "Invalid parent id"
address <- addressDao.findById(parent.get.addressId) whenUndefined "Invalid address id"
} yield {
// business logic
}
result.recover {
case fpe: FutureProcessingException => BadRequest(fpe.getMessage)
case t: Throwable => InternalServerError
}
}
The above approach ensured that all exceptions caused by missing Option value are handled as a BadRequest with specific message about what exactly failed. All other failures are treated as InternalServerError. You can log the exact exception with stack trace in order to help debug.
Related
The following code returns a Future.
val findUserFuture: Future[Option[User]] = userRepo.findOne(userKeys)
Then I process the Future
findUserFuture.flatMap {....}
.recover{...}
fineOne returns the Future and the Future wraps call to getOneById
def findOne(userKeys:UserKeys):Future[Option[User]] = {
Future{
//val loginInfo:LoginInfo = LoginInfo(userKeys.providerID,userKeys.authProvider)
val userOption:Option[User] = getOneById(userKeys)
userOption
}
}
I suppose that recover will be called if Future returned by findOne fails i.e. throws an Exception. So I am simulating that by making getOneById throw an exception.
when(mockUserRepository.findOne(userKeys)).thenReturn(Future(Some(user)))
when(mockUserRepository.getOneById(userKeys)).thenThrow(classOf[RuntimeException]) //simulating database error
But the unit test doesn't throw an exception and the test proceeds using value Future(Some(User)).
I also tried throwing the exception from findOne - when(mockUserRepository.findOne(userKeys)).thenThrow(classOf[RuntimeException]) but the test case stops
with the following two prints and the .recover of the Future is not called
java.lang.RuntimeException was thrown.
java.lang.RuntimeException
This findUserFuture: Future[Option[User]] or userRepo.findOne returns future,
hence you need to return Future.failed in your mock.
For ex.
when(mockUserRepository.findOne(userKeys)).thenReturn(Future(Some(user)))
when(mockUserRepository.getOneById(userKeys)).thenReturn(Future.failed(new RuntimeException("network failure"))
Find below complete working test to simulate your use case :
test("mock future test") {
case class User(name: String)
case class UserNotFoundException(name: String) extends Exception
trait UserRepo {
def findOne(name: String): Future[Option[User]]
}
val name = "bob"
val dummyUser = User("dummy")
val userRepo = mock[UserRepo]
when(userRepo.findOne(name)).thenReturn(Future.failed(new RuntimeException()))
val userF = userRepo
.findOne(name)
.flatMap {
case Some(user) ⇒ Future.successful(user)
case None ⇒ Future.failed(UserNotFoundException(name))
}
.recover {
case NonFatal(_) ⇒ dummyUser
}
userF.futureValue shouldBe dummyUser
}
Update *
After looking at the original post closely, I found small mistake in the way you are mocking.
try below:
when(mockUserRepository.findOne(userKeys)).thenCallRealMethod()
when(mockUserRepository.getOneById(userKeys)).thenThrow(classOf[RuntimeException])
Notice thenCallRealMethod() here, earlier you were mocking findOne to return future with successful value which means original method was not getting called which in turn was not calling getOneById
You can't mock the type you want to test, a mock has nothing of the original behaviour of that type.
If you wanna stub just some behaviour of the class under test (or any other type), you should use a spy, then you would only do
when(spyUserRepository.getOneById(userKeys)).thenThrow(classOf[RuntimeException])
then call spyUserRepository.findOne(userKeys) and assert that it returns a Failed future
That said, it seems you have the responsabilities a bit mixed up here, I'd suggest having a second look to your design as having to resort to use spys for this looks like a big code smell for me.
My goal is to do some database queries from the async controller, then return the answer.
I'm playing with the example project, for now just simulating the DB queries with a sleep, but what I noticed is that whatever I do, the REST interface won't even start the sleep of the second query until the first one finishes.
E.g.: If I call the REST interface from one tab in the browser, then 1 second later again from an another tab, I'd expect that the second one gets the reply too in 10 seconds, but actually it's 19.
Also it doesn't seem to use the "database-io" pool either:
1: application-akka.actor.default-dispatcher-2
2: application-akka.actor.default-dispatcher-5
My code:
#Singleton
class AsyncController #Inject()(cc: ControllerComponents, actorSystem: ActorSystem) extends AbstractController(cc) {
implicit val executionContext = actorSystem.dispatchers.lookup("database-io")
def message = Action.async {
getFutureMessage().map { msg => Ok(msg) }
}
private def getFutureMessage(): Future[String] = {
val defaultThreadPool = Thread.currentThread().getName;
println(s"""1: $defaultThreadPool""")
val promise: Promise[String] = Promise[String]()
actorSystem.scheduler.scheduleOnce(0 second) {
val blockingPool = Thread.currentThread().getName;
println(s"""2: $blockingPool""")
Thread.sleep(10000)
promise.success("Hi!")
}(actorSystem.dispatcher)
promise.future
}
}
It could be two reasons for this behavior:
You use the development mode (1 thread), or your product configuration is configured only for one thread.
The browser blocks the second request until receiving the response from the first. This phrase: "If I call the REST interface from one tab in the browser." Try to do the same from different browsers.
You need to avoid blocking code. Basically:
You can a method that returns the Future.
You map into it.
You recover any failure the Future result might bring.
Lets say I have:
def userAge (userId: String): Future[Int] = ???
Then you map into it:
userAge.map{
age => ??? //everything is ok
}.recover{ case e: Throwable => ??? //Do something when it fails
Note that if you have more than one call the other map becomes flatMap because you want Future[...] something and not Future[Future[...]].
Please excuse my poor understanding of Scala. I'm just a Java developer that wants to get something working in the Play Framework. I even attempted to implement a trait using Java code, but I got even more obscure errors. I have the following Scala code:
package models
import scala.concurrent.Future
class SettableFuture[T](name: String) extends Future[T] {
var assignedValue: T
def set(newValue: T) =
assignedValue = newValue
//override abstract methods in Future[T]
def ready(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): models.SettableFuture[T] =
this
def result(atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait): T =
assignedValue
def isCompleted: Boolean =
false
def onComplete[U](func: scala.util.Try[T] => U)(implicit executor: scala.concurrent.ExecutionContext): Unit =
null
def value: Option[scala.util.Try[T]] =
null
}
And here's my error:
overriding method ready in trait Awaitable of type (atMost: scala.concurrent.duration.Duration)(implicit permit: scala.concurrent.CanAwait)SettableFuture.this.type; method ready has incompatible type
Ignore the return values of the methods for now, they're nonsensical because I'm just trying to fix all the compile errors.
I simply copied the method stubs from the compile time exception when extending a trait without overriding its abstract methods and pasted them into my source file. I don't understand why I'm still getting errors. I took a look at the signature for ready() in Awaitable and it looks like the return type should in fact be the class.
EDIT: the reason why I want to implement this is because in the Promise/Future Scala API, I can only find things that let me asynchronously execute long-running, blocking tasks. What I'm after is something that lets execution of a request be suspended until something of interest sets a value in the SettableFuture instance, which completes a Promise to send a response. In this way, it's somewhat like a continuation. Anyway, here is the working code that I ended up with:
package models
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import scala.concurrent.CanAwait
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import scala.util.Try
class SettableFuture[T]() extends Future[T] {
private final val ValueNotSet = 0
private final val ValueBeingSet = 1
private final val ValueSet = 2
private val valueStatus: AtomicInteger = new AtomicInteger(ValueNotSet)
private val onCompleteWaitHandle: CountDownLatch = new CountDownLatch(1)
private var onComplete: Try[T] => _ = _
private var assignedValue: T = _
/** Set a value and complete this Future.
*
* Returns false if the value has already been set by a past call to this method.
* Otherwise, marks this Future as complete, executes the function passed to
* onComplete, and finally returns true.
*/
def set(newValue: T): Boolean = {
//set value and trigger onComplete only once
if (valueStatus.compareAndSet(ValueNotSet, ValueBeingSet)) {
assignedValue = newValue
valueStatus.set(ValueSet)
onCompleteWaitHandle.countDown()
if (onComplete != null)
onComplete(Try(assignedValue))
true
}
false
}
//override abstract methods in the Future[T] trait
def ready(atMost: Duration)(implicit permit: CanAwait): this.type = {
onCompleteWaitHandle.await(atMost.length, atMost.unit)
this
}
def result(atMost: Duration)(implicit permit: CanAwait): T = {
ready(atMost)
assignedValue
}
def isCompleted: Boolean = (valueStatus.get() == ValueSet)
def onComplete[U](func: Try[T] => U)(implicit executor: ExecutionContext): Unit =
onComplete = func
def value: Option[Try[T]] = {
if (!isCompleted)
None
Some(Try(assignedValue))
}
}
In terms of the specific error you are getting, the ready method you are overriding has a return type of Awaitable.this.type - ie. the specific type of this instance of Awaitable (the super type of Future, so that in Future, this method is seen to have return type Future.this.type). For your SettableFuture class, this means the return type for the ready method needs to be models.SettableFuture.this.type.
Other minor problems you can expect to hit: the onComplete method's implementation should be {}, not null, as the latter is a return of type Null.type, not Unit, and the var assignedValue needs to be initialised in a non-abstract class, which can be done by adding = _ to the line defining the variable (although you really want to make it at least protected, and provide an accessor which will check if it has been set - maybe by changing the variable to an Option[T] initialised to None, or else maintaining a Boolean flag that can be checked in the accessor, and which is set to true by the set method).
In terms of what it looks like you are trying to achieve, however, you might just want to check out scala.concurrent.Promise, which represents a "promise of a future result". It has a method future that returns a Future, and various complete, completeWith, and similar methods that can be used to set the Promise's value, which in turn will cause the associated Future to become ready/completed.
The SettableFuture class unnecessarily mixes the two concerns that the Future and Promise traits were designed to separate:
asynchronous provision of a value (Promise), and
waiting for and reacting to that provision (Future)
Rather than thinking of a Future as an asynchronous, long-running, blocking computation, it may help to think of it simply as a value that may be provided at some future time. You can react to provision of that value in a number of ways, including registering a callback or mapping it to some other value. For example, in Play one will often suspend processing of a request with a pattern like this (in Scala):
def handleRequest = Action {
Async {
gimmeAFuture().map(value => Ok(value))
}
}
def gimmeAFuture(): Future[JsValue] = // ...
The gimmeAFuture method returns a Future, but the request handling code doesn't care about how the value is computed. It could be
computed immediately with Future.successful,
computed asynchronously with Future.apply, or
supplied by the completion of a Promise
As an example of the latter, the gimmeAFuture method might be implemented as follows:
def gimmeAFuture: Future[JsValue] = {
val p = Promise.apply[JsValue]()
// asynchronously complete the promise 30 seconds from now
scheduler.scheduleOnce(30.seconds)(p.complete(Success(someJsObject)))
// return the future immediately
p.future
}
Of course, you could implement that method however you want. The key is that something will need to hold on to that Promise object and complete it with a value in order to resume handling of the request. The request handler itself does not get a reference to the Promise object, since it only cares about the value that will be computed (i.e., the Promise's Future).
I revisited this question after finding this link and I realized why there was so much confusion.
I was planning on using the SettableFuture class because I couldn't find anything like it that already existed in the Play Java API. I wanted something equivalent to a TaskCompletionSource in .NET, and Aaron's answer made it really clear that Scala had exactly what I needed. Unfortunately, I couldn't find the equivalent in Play's Java API.
That link cleared up exactly why I was having so much difficulty over something that should have been so simple. Thanks all for answering my question!
The usual way of detecting the type of message received in scala actors is by
loop{
react{
case x: String =>
}
}
However, I want to know how can we override this implementation of react construct so that we can do implicit logging of the message that is received.
I am trying to implement a use case mentioned below ->
1. Before a message is matched to any case class, I want to write a log statement on console / file showing the occurance of the message.
2. We can log these messages explicitly by println() / log4j logging . However, I want to design a generic logger for scala actors which will log all the messages sent or received.
Any help in this regard will be helpful.
Thanks in advance
First, be aware that the Scala actors library is being deprecated in favor of Akka. So this answer won't be helpful very long (though the other actors library will continue to be available for a while--and since it's open source potentially forever if people want to maintain it).
Anyway, the react method is defined in scala.actors.Actor. Simply fail to import it, or hide it with your own. Your own what?
Well, the method just takes a PartialFunction[Any,Unit]. So, your should also:
def react(pf: PartialFunction[Any,Unit]): Nothing = { /*how?;*/ Actor.react(/*what?*/) }
You really only have access to the partial function, and you have to defer to Actor.react to do what you want. So you need to wrap pf in another PartialFunction that performs your logging. So you can
val qf = new PartialFunction[Any,Unit] {
def isDefinedAt(a: Any) = pf.isDefinedAt(a)
def apply(a: Any): Unit = {
log(a) // Maybe add more logic to know what a is
pf(a)
}
}
If you want to see messages that come in and get examined but are not actually consumed, you could do more with isDefinedAt also.
So, obviously enough, I hope, /*how?*/ is the above to define (create) qf, and /*what?*/ is just qf.
If you want to know whether a is a case class, the answer is that you cannot (by design). A case class is just syntactic sugar on top of ordinary Scala features; it's just there to save you typing. See, for instance, this question.
However, you can get pretty close by pattern matching for Product and checking whether it has a copy method:
case class M(i: Int)
val a: Any = M(5)
scala> a match {
case p: Product if p.getClass.getMethods.exists(_.getName=="copy") => println("Yes")
case _ => println("No")
}
Yes
If you really want to get fancy, check if copy has the same number and type of parameters as the constructor.
//Following is a code for a logReact Method that does the same thing as react but also logs the message received hope this works for you
import scala.actors.Actor;
import scala.actors.Actor._
trait ActorLogging extends Actor {
def logReact(handler: PartialFunction[Any, Unit]): Nothing = {
val handler2: PartialFunction[Any, Unit] = {
case x =>
println("Inside Logs -- with message recieved -- " + x.toString);
handler.apply(x);
}
super.react(handler2)
}
}
class sumAct extends Actor with ActorLogging {
def act() {
loop {
logReact {
case a: Int =>
println("Inside actor Sum Act Received the message -- " + a)
exit;
}
}
}
}
object ActorLog {
def main(args: Array[String]): Unit = {
var s: sumAct = new sumAct;
s.start();
s ! 1.toInt;
}
}
I'm using the Netty library (version 4 from GitHub). It works great in Scala, but I am hoping for my library to be able to use continuation passing style for the asynchronous waiting.
Traditionally with Netty you would do something like this (an example asynchronous connect operation):
//client is a ClientBootstrap
val future:ChannelFuture = client.connect(remoteAddr);
future.addListener(new ChannelFutureListener {
def operationComplete (f:ChannelFuture) = {
//here goes the code that happens when the connection is made
}
})
If you are implementing a library (which I am) then you basically have three simple options to allow the user of the library to do stuff after the connection is made:
Just return the ChannelFuture from your connect method and let the user deal with it - this doesn't provide much abstraction from netty.
Take a ChannelFutureListener as a parameter of your connect method and add it as a listener to the ChannelFuture.
Take a callback function object as a parameter of your connect method and call that from within the ChannelFutureListener that you create (this would make for a callback-driven style somewhat like node.js)
What I am trying to do is a fourth option; I didn't include it in the count above because it is not simple.
I want to use scala delimited continuations to make the use of the library be somewhat like a blocking library, but it will be nonblocking behind the scenes:
class MyLibraryClient {
def connect(remoteAddr:SocketAddress) = {
shift { retrn: (Unit => Unit) => {
val future:ChannelFuture = client.connect(remoteAddr);
future.addListener(new ChannelFutureListener {
def operationComplete(f:ChannelFuture) = {
retrn();
}
});
}
}
}
}
Imagine other read/write operations being implemented in the same fashion. The goal of this being that the user's code can look more like this:
reset {
val conn = new MyLibraryClient();
conn.connect(new InetSocketAddress("127.0.0.1", 1337));
println("This will happen after the connection is finished");
}
In other words, the program will look like a simple blocking-style program but behind the scenes there won't be any blocking or threading.
The trouble I'm running into is that I don't fully understand how the typing of delimited continuations work. When I try to implement it in the above way, the compiler complains that my operationComplete implementation actually returns Unit #scala.util.continuations.cpsParam[Unit,Unit => Unit] instead of Unit. I get that there is sort of a "gotcha" in scala's CPS in that you must annotate a shift method's return type with #suspendable, which gets passed up the call stack until the reset, but there doesn't seem to be any way to reconcile that with a pre-existing Java library that has no concept of delimited continuations.
I feel like there really must be a way around this - if Swarm can serialize continuations and jam them over the network to be computed elsewhere, then it must be possible to simply call a continuation from a pre-existing Java class. But I can't figure out how it can be done. Would I have to rewrite entire parts of netty in Scala in order to make this happen?
I found this explanation of Scala's continuations extremely helpful when I started out. In particular pay attention to the parts where he explains shift[A, B, C] and reset[B, C]. Adding a dummy null as the last statement of operationComplete should help.
Btw, you need to invoke retrn() inside another reset if it may have a shift nested inside it.
Edit: Here is a working example
import scala.util.continuations._
import java.util.concurrent.Executors
object Test {
val execService = Executors.newFixedThreadPool(2)
def main(args: Array[String]): Unit = {
reset {
val conn = new MyLibraryClient();
conn.connect("127.0.0.1");
println("This will happen after the connection is finished");
}
println("Outside reset");
}
}
class ChannelFuture {
def addListener(listener: ChannelFutureListener): Unit = {
val future = this
Test.execService.submit(new Runnable {
def run(): Unit = {
listener.operationComplete(future)
}
})
}
}
trait ChannelFutureListener {
def operationComplete(f: ChannelFuture): Unit
}
class MyLibraryClient {
def connect(remoteAddr: String): Unit#cps[Unit] = {
shift {
retrn: (Unit => Unit) => {
val future: ChannelFuture = new ChannelFuture()
future.addListener(new ChannelFutureListener {
def operationComplete(f: ChannelFuture): Unit = {
println("operationComplete starts")
retrn();
null
}
});
}
}
}
}
with a possible output:
Outside reset
operationComplete starts
This will happen after the connection is finished