Scala 2.13 migration - scala

I am migrating Play 2.8.8 project from Scala 2.12 to 2.13.
I have a really weird error in the Play routes file:
method right in class Either is deprecated (since 2.13.0): Either is now right-biased, use methods directly on Either
There is no .right calls in the routes file, in the generated Scala routes file or in the related controllers.
Route file:
POST /roles/:id controllers.Authentication.api.RolesResource.addRoleToAccount(id:models.users.AccountId)
DELETE /roles/:id controllers.Authentication.api.RolesResource.removeRoleFromAccount(id:models.users.AccountId)
GET /roles/:id controllers.Authentication.api.RolesResource.getRolesForAccount(id:models.users.AccountId)
Thanks for any guidance what might be the source of this error.

I think the reason is in play.core.routing.GeneratedRouter class.
From my route file this method:
(for {
a1 <- pa1.value.right
a2 <- pa2.value.right}
yield (a1, a2))
.fold(badRequest, { case (a1, a2) => generator(a1, a2) })
}
It contains calls to deprecated .right function.

Related

When would request.attrs.get in a Scala Play custom filter return None?

In an answer to "How to run filter on demand scala play framework", the following code is suggested:
// in your filter
val handlerDef: Option[HandlerDef] = request.attrs.get(Router.Attrs.HandlerDef)
I'm not sure what's happening here - is it safe to .get on this val (to get it out of the Option)? In what scenarios would this code result in a None (ie, when would Router.Attrs.HandlerDef not be present)?
I'm working with Scala and PlayFramework 2.6.
According to Route modifier tags
Please be aware that the HandlerDef request attribute exists only when
using a router generated by Play from a routes file. This attribute is
not added when the routes are defined in code, for example using the
Scala SIRD or Java RoutingDsl. In this case
request.attrs.get(HandlerDef) will return None in Scala or null in
Java. Keep this in mind when creating filters.
Hence if you are using routes file then Router.Attrs.HandlerDef should always be available. As a shorthand instead of
val handlerDef: HandlerDef = request.attrs.get(Router.Attrs.HandlerDef).get
your can use apply sugar like so
val handlerDef: HandlerDef = request.attrs(Router.Attrs.HandlerDef)

Why scala #tailrec can't be used on Option.flatMap?

In scala, the following 2 functions serve exactly the same purpose:
#tailrec
final def fn(str: String): Option[String] = {
Option(str).filter(_.nonEmpty).flatMap { v =>
fn(v.drop(1))
}
}
#tailrec
final def fn2(str: String): Option[String] = {
Option(str).filter(_.nonEmpty) match {
case None => None
case Some(v) => fn2(v.drop(1))
}
}
However #tailrec only works in second case, in the first case it will generate the following error:
Error: could not optimize #tailrec annotated method fn: it contains a
recursive call not in tail position
Option(str).filter(_.nonEmpty).flatMap { v =>
Why this error was given? And why these 2 codes generate different kinds JVM bytecode
For fn to be tail-recursive, the recursive call must be the last action in the function. If you pass fn to another function such as flatMap then the other function is free to perform other actions after calling fn and therefore the compiler cannot be sure that it is tail recursive.
In some cases the compiler could detect that calling fn is the last action in the other function, but not in the general case. And this would rely on a specific implementation of that other function so the tailrec annotation might become invalid if that other function were changed, which is an undesirable dependency.
Specifically for the last question:
And why these 2 codes generate different kinds JVM bytecode
Because on JVM there's no guarantee that the JAR containing Option class at runtime is the same as was seen at compile-time. This is good, because otherwise even minor versions of libraries (including standard Java and Scala libraries) would be incompatible, and you'd need all dependencies to be using the same minor version of their common dependencies.
If that class doesn't have a suitable flatMap method, you'll get AbstractMethodError, but otherwise semantics of Scala require that its flatMap method must be called. So the compiler has to emit bytecode to actually call the method.
Kotlin works around this by using inline functions and Scala 3 will support them too, but I don't know if it'll use them for such cases.
Consider the following:
List('a', 'b').flatMap(List(_,'g')) //res0: List[Char] = List(a, g, b, g)
I seems pretty obvious that flatMap() is doing some internal post-processing in order to achieve that result. How else would List('a','g') get combined with List('b','g')?

Read and understand the spray-routing DSL

I am new to spray.
I have work with several strange (for me) programming languages like python, JQuery, etc... With them I could at least understand what some code segment do.
Unfortunately with Spray, I can not read and understand even a simple code.
Could some one please help me to read (describe with word, what the code do) the following simple code block.
Note: Very high level I know, this will pick the url parameter and add them together. But what I want is, understand this code block crystal clearly, as I could teach to someone else. HNil, Directive1, Directive1, :: are some what strange for me.
val twoIntParameters: Directive[Int :: Int :: HNil] =
parameters('a.as[Int], 'b.as[Int])
val myDirective: Directive1[String] =
twoIntParameters.hmap {
case a :: b :: HNil => (a + b).toString
}
// test `myDirective` using the testkit DSL
Get("/?a=2&b=5") ~> myDirective(x => complete(x)) ~> check {
responseAs[String] === "7"
}
spray-routing is build around the concept of Directive.
You can think of a Directive as a transformation over an HTTP request.
The cardinality associated with a directive is the number of arguments is passes down the transform chain after performing the transformation.
Directive0 is a directive that doesn't provide (or extract) any argument.
Directive1[A] provides one argument of type A.
Directive[A :: B :: HNil] provides 2 arguments of types A and B, or - to be more precise - provides an heterogeneous list made of A and B (the implementation is a shapeless's HList).
Let's take the examples in your code
val twoIntParameters: Directive[Int :: Int :: HNil] =
parameters('a.as[Int], 'b.as[Int])
You're defining a new directive that extracts two integers from the HTTP request, i.e. has the type Directive[Int :: Int :: HNil].
The implementation simply leverages a directive provided already by spray, i.e. parameters.
parameters is a directive that allows to extract the query parameters from a HTTP request and convert them to a specific type, in this case Int for both parameters.
val myDirective: Directive1[String] =
twoIntParameters.hmap {
case a :: b :: HNil => (a + b).toString
}
myDirective is a directive that extracts one parameter of type String.
Its implementation uses the previously defined twoIntParameters directive and maps over its result, applying a transformation to it.
In this case we're taking the two Int, summing them and turning the result into a String.
So, what's with the hmap? That's just a way provided by spray of working with Directives that return a shapeless HList. hmap requires a function that HList to anything, in this case a String.
HLists can be pattern matched over, just like a normal scala List, and that's what you're seeing in the example.
Finally, this is just an idea of how directives work from a functional point of view.
If you want to understand the fine details of the DSL syntax, you will have to dig a little further and read about the Magnet Pattern.
Here I found a very good workshop.
https://www.youtube.com/watch?v=XPuOlpWEvmw

Exception handling in scala

I am working on an application with Scala. I am trying to implement Exception Handling in the application. I tried using Either for handling the exceptions. For simple cases, it seems to be enough to handle exceptions. However, when I need to get results from multiple tables by joins, the exception handling is creating more issues than solving. My application structure is explained below:
Using repository pattern for the database operations which defines all the database interaction operations. For eg, I have a central repository which defines findAll, findById, insert, delete, update, exists etc. My findAll methods signature has been changed to Either[CustomException, List[TEntity]], similarly findById methods type is Either[CustomException, Option[TEntity]].
Now assume that, If I need to fetch employees from database in my method, i will be doing something like below :
def getVehicleById(id:Long) = {
val vehicle = repository.findById(id)
//i have one-to-one mapping with Employee table for the driver of the vehicle
val driver = empRepository.findById(vehicle.driverId)
}
Now the type of vehicle will be Either[CustomException, Option[Vehicle]] and type of driver is Either[CustomException, Employee]
If i need to do any more operation after getting the results, i have to use case Right/Left and then do that. The problem is that, may be inside the Right case, I might need to join with another table, which makes the result of that as again Either[CustomException, Entity]. if any error occurs in that operation, i need to again use try catch block.
I feel that this kind of hanling becomes very difficult to manage when the code complexity increases, and also I will have a lot of boiler plate code to handle these situations, which goes against Scala principle itself.
So my question is, how can I handle exception in a better way without much boiler plate code.
Note : I am coming from a Java background, have been working on Scala only for a couple of months now.
EDIT
Adding Sample Code with Try :
This sample is very close to the requirement I have.
import scala.util._
def checkTry:Try[List[Int]] = Success(List(2))
def checkTryStr:Try[String] = Success("Asd")
def getVehicleWithDriver = for {
a <- checkTry
c <- a
b <- checkTryStr
}yield {
(c,b)
}
getVehicleWithDriver
But with the bove code, I am getting compilation errors.
Error:(9, 6) type mismatch;
found : scala.util.Try[(Int, String)]
required: scala.collection.GenTraversableOnce[?]
b <- checkTryStr
^
Error:(9, 6) type mismatch;
found : scala.util.Try[(Int, String)]
required: scala.collection.GenTraversableOnce[?]
b <- checkTryStr
^
Error:(8, 6) type mismatch;
found : List[Nothing]
required: scala.util.Try[?]
c <- a
^
You want to use the for/yield sugar. You can either get in the habit of putting .right on all your Eithers, or as #Gangstead suggests, use \/ from Scalaz. (There are certainly scary parts of Scalaz - I've been using it for 4 years and am still intimidated by e.g. Strength - but it's perfectly possible to start with the easy parts and work your way up).
for {
vehicle <- repository.findById(id).right
driver <- empRepository.findById(vehicle.driverId).right
somethingElse <- somePossiblyFailingComputation.right
} yield somethingElse
//Don't need the .right if you're using Scalaz \/
Other vital hints: when you want to apply an effectful function to a List, you want to use Scalaz traverse:
vehicleList <- vehicleIdList.traverse(repository.findById) //assuming you're using \/
//might need a few .right if you're using Either
When you're calling Java code that might throw an exception, use scala.util.control.Exception's catching:
val myEither = catching(classOf[SomeException]) either someJavaMethodThatThrows()
// (...).disjunction if you're using \/.
If you need to work with another kind of "effectful context" at the same time as working with Either/\/, you'll have to start looking at monad transformers, but it might be best to get comfortable with just Either first.
Hope that helps; best of luck, hope you like Scala.
Take a look at Scalaz's disjunction \/.
A warning: Scalaz is hardcore scala written by hardcore guys.
Take a look at Brendon McAdams' (#Rit) presentation about "Scalaz' Gateway Drugs". He's much more approachable for programmers coming from Java, and he keeps it very practicall
You want to use Try, not Either. It is a monad, so you can map or flatMap it, or use it in a for comprehension. It looks pretty elegant actually.
def getVehicleWithDriver(id: String): Try [(Vehicle, Driver)] = for {
vehicle <- repository. findById(id)
driver <- empRepository.findById(vehicle.driverId)
} yield {
(vehicle, driver)
}

Searching the Scala documentation for #::

I am trying to find the documentation for the Scala operator method #::. I believe that it is defined in the Stream class because of an example I found that uses it.
My question is not particular to this method (although I would like to know where the docs are), but how to search the Scala docs in general. I tried entering #:: in the search box in the upper left of the documentation page (2.8.1), but found nothing.
I suggest using the Reference Index - it's designed specifically to look for any kind of symbol (class, traits, methods, vals, vars) regardless of it's hierarchical position - contrasting with the Scaladoc's left index which doesn't show inner classes, traits or objects.
Unfortunately it's only available in the nightly. You can see the whole thing at nightly Scaladoc. Notice the upper box in the left frame, above the index.
Hope it will be bundled with Scala 2.9.0.
Edit As of 2.9.0, the reference index started to be bundle with Scaladoc. No need to go to the nightly docs now.
As others have already mentioned, #:: is defined on scala.collection.immutable.Stream.ConsWrapper. I just wanted to take a minute to elaborate on why that is.
In general, to call an operator on an object, that object needs to exist. However, the idea with a Stream is the tail of the stream is not evaluated until it needs to be. So consider the following stream:
def fibs(a:Int,b:Int):Stream[Int] = a #:: fibs(b,a+b)
Ordinarily, we would need to evaluate the recursive fibs call so that we could call the #:: operator on it. This would lead to runaway recursion. This is NOT what we want. What we want is for the reciever to be a by-name Stream. Hence the ConsWrapper:
The constructor for ConsWrapper is class ConsWrapper[T](tail: => Stream[T]) taking a by-name Stream, and it's created through an implicit conversion Stream.consWrapper[T](stream: => Stream[T]), which also takes a by-name Stream.
Hence, we have performed an implicit conversion on the result of a function that has not yet been called, and we have mimiced the effect of calling #:: with a by-name this reference.
The problem here is that the scaladoc search does not allow you to look for an inner class/object (i.e. whose parent is not a package). The declaration of #:: is either Stream.#:: or Stream.ConsWrapper.#:::
object Stream {
//STUFF
/** An extractor that allows to pattern match streams with `#::`.
*/
object #:: {
def unapply[A](xs: Stream[A]): Option[(A, Stream[A])] =
if (xs.isEmpty) None
else Some((xs.head, xs.tail))
}
class ConsWrapper[A](tl: => Stream[A]) {
def #::(hd: A): Stream[A] = new Stream.Cons(hd, tl)
def #:::(prefix: Stream[A]): Stream[A] = prefix append tl
}
//MORE STUFF
}
You could request this as an RFE to the scaladoc tool in trac.
In IntelliJ IDEA's scala plugin, you could have used symbol lookup (CTRL+ ALT+ SHIFT+ N) and typed #:: and this would have brought up both declarations of #:: immediately.
Well, normally, if we see
foo bar baz
then bar is a method, defined for foo, so we first look in the class/object - definition of foo, then the inheritance/trait tree upwards (+ in implicit conversions to and from foo, in the current file, and in (directly) included files).
Except 'bar' ends in a colon, which is the case here. Then it is to be read in reverse order -
foo bar: baz
is not
foo.bar: (baz)
, but
baz.bar: (foo)
So we have to look up in the way described above, but not for foo, but for baz.
That particular method is defined in a nested class inside of Stream, called scala.collection.immutable.Stream.ConsWrapper.
And no, I have absolutely no idea how one would go about finding it. I only stumbled across it by accident. And even though I knew where to find it now, when I wanted to post the link to the class here in my answer, I still couldn't find it on the first (and even second and third) try.