scala concepts involved in db withSession { implicit session => - scala

I am working in scala. I went through maximum all the concepts like high ordered function, curried functions, macros etc. But while working with slick i didn't understand this code snippet. db withSession { implicit session =>
What I understood is JdbcBackend.DatabaseDef is calling withSession method. So after that I dont know what is happening in that implementation. Please guys let me know or do I need to know even concepts related to this implementation. Tq

You already seem to know the concepts. withSession is a function defined on db that takes a single function as it's argument, i.e. Higher-order function: https://docs.scala-lang.org/tutorials/tour/higher-order-functions.html.html
Scala will allow you to omit the dots when calling that function, i.e. Infix notation: https://docs.scala-lang.org/style/method-invocation.html#infix-notation
The curly brackets just create a standard code block, but as you're using => you end up with a block that defines a function that is then passed to withSession as single argument using the infix notation.

withSession method separates business logic from resource management logic. db.withSession provides a connection to the database to a user, then a user can use it, and after the body of withSession block is finished (normally or exceptionally) this connection is returned to the connection pool.
This approach is similar to java's tryWithResource idiom.

Related

Concatenate a vector in Gatling

I'm trying to concatenate a vector into a string in order to insert it into a get call.
Previously in my code I use the following:
.exec(http("request_11")
.get("/api/data/users/${userId}")
.headers(headers_3)
.check(jsonPath("$..users[0].links.orgRoles[*]").findAll.saveAs("orgRoles")))
Which gives me an orgRoles session variable of:
Vector(b2b5fb81-4025-48a5-9890-a6ec7d64f317, 744db047-1477-4bb6-9c55-70071ce41cb8, 423b0b07-7bfa-416a-9b95-cc1d75d7d781)
I'd then like to use this concatenated session variable like so:
.exec(http("request_50")
.get("/api/data/orgRoles/${orgRoles}")
Which would, in effect, do the following get call:
.exec(http("request_50")
.get("/api/data/orgRoles/b2b5fb81-4025-48a5-9890-a6ec7d64f317,744db047-1477-4bb6-9c55-70071ce41cb8,423b0b07-7bfa-416a-9b95-cc1d75d7d781")
.headers(headers_3))
I'm brand new to Gatling and Scala, and have done a ton of research. I found the following answer which offers that
session => session("itemIds").validate[Seq[String]].map(_.mkString(","))
is the right approach. In turn, I've tried to manipulate the session variable with the following:
...
.exec { session =>
session("orgRoles").map(_.mkString(","))
}
.exec(http("request_50")
.get("/api/data/orgRoles/${orgRoles}")
.headers(headers_3))
...
Yet end up with the error:
value mkString is not a member of io.gatling.core.session.SessionAttribute
Any suggestions on moving forward?
The error you are getting is because by:
session("orgRoles")
you are calling Session.apply method at session instance (for more see source code). The apply method returns SessionAttribute instance, which has following methods:
// Use when you are certain that key exists in session, otherwise you'll get exception which you has to handle
def as[T: NotNothing]: T
// Use when you want to handle also not existing key and you can react to `None` case
def asOption[T: TypeCaster: ClassTag: NotNothing]: Option[T]
// Use when you want to code against success path and use combinators provided by `Validation`
def validate[T: TypeCaster: ClassTag: NotNothing]: Validation[T]
Each servers different purpose (see comments). All above mentioned methods of SessionAttribute are just getters from session. Their only purpose is to provide you a value of the key stored in session in any form.
Only after getting the value you can do anything with it. The safest bet is to use validate method which provides common combinators (used in all Scala collections) map and flatMap to manipulate the value when it exist. You can find more about Validation concept here. Hence your code should look like:
// Just getting from session and concatenating
session => session("orgRoles").validate[Seq[String]].map( _.mkString(",") )
// also storing back to session
session => session.set("orgRoles", session("orgRoles").validate[Seq[String]].map( _.mkString(",") ))
This is also what you already wrote above. But you are already using check DSL method and thus you can use transform() directly in your first call as:
.exec(
http("request_11")
.get("/api/data/users/${userId}")
.headers(headers_3)
.check(
jsonPath("$..users[0].links.orgRoles[*]")
.findAll
.transform( _.mkString(",") )
.saveAs("orgRoles")
)
)
It's straightforward, easier to follow and there is no temporary save to Session. Even the function which you put to transform is easier, while it is defined as A => B thus plain transformation. Check-out more about transforming here.
Have you tried calling the toString or maybe groupHierarchy?
session => session("itemIds").validate[Seq[String]].map(_.toString.mkString(","))
session => session("itemIds").validate[Seq[String]].map(_.groupHierarchy.mkString(","))
take a look at: https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/session/Session.scala
I ended up solving it with this:
.exec(session =>
session.set("orgRolesConcat", session("orgRoles").as[Seq[String]].mkString(",")))

in scala what is cleaner code - to def (~member) versus pass function parameter?

Which is cleaner?
def version
trait Foo {
def db: DB
def save() = db.save()
def load() = db.load()
}
versus parametric version:
trait Foo {
def save(db: DB) = db.save()
def load(db: DB) = db.load()
}
(left out intentionaly other parameters/members I want to focus on this one).
I have to say that when I look at complex projects I thank god when functions are taking all their dependencies in
I can unit test them easily without overriding members, the functions tells me all that it's dependent upon on its signature.
I don't have to read their internal code to understand better what the function does, I have its name, I have its input, I have its output all in function signature.
But I also noticed that in scala its very conventional to use the def version, and I have to say that this code when it comes bundled in complex projects such code is much less readable for me. Am I missing something?
I think in this case it highly depends on what the relationship is between Foo and DB. Would it ever be the case that a single instance of Foo would use one DB for load and another for save? If yes, then DB isn't really a dependency of Foo and the first example makes no sense. But it seems to me that the answer is no, that if you call load with one DB, you'll be using the same DB when you call save.
In your first example, that information is encoded into the type system. You're effectively letting the compiler do some correctness checking for you, since now you're enforcing at compile-time that for a single Foo, load and save will be called on the same DB (yes it's possible that db is a var, but that in itself is another issue).
Furthermore, it seems inevitable that you're just going to be passing around a DB every place you pass a Foo. Suppose you have a function that uses Foo. In the first example, your function would look like
def loadFoo(foo: Foo) {
foo.load()
}
whereas in the second it would look like:
def loadFoo(foo: Foo, db: DB) {
foo.load(db)
}
So all you've done is lengthened every function signature and opened up room for errors.
Lastly, I would argue that your points about unit testing and not needing to read a function's code are invalid. In the first example, it's true that you can't see all of load's dependencies just by looking at the function signature. But load is not an isolated function, it is a method that is part of a trait. A method is not identical to a plain old function and they exist in the context of their defining trait.
In other words, you should not be thinking about unit testing the functions, but rather unit testing the trait. They're a package deal and you should have no expectations that their behavior is independent of each other. If you do want that kind of independance, than Foo should be an object which basically makes load and save static methods (although even then objects can have internal state, but that is far less idiomatic).
Plus, you can never really tell what a function is doing just by looking at its dependencies. After all I could write a function:
def save(db: DB){
throw new Exception("hello!!")
}

How do scala implicit values work?

This is not a question about implicit in general - I know how it works. It's about one specific construct. Here comes a quite common patten in myBatis for Scala:
manager.readOnly { implicit session => {
//Code block: Do some DB operations in session
}
}
Definition of readOnly can be found here: https://github.com/mybatis/scala/blob/master/mybatis-scala-core/src/main/scala/org/mybatis/scala/session/SessionManager.scala
How I read it: Call a readOnly method on manager with its argument being a function that takes session as an argument.
My question is: Where implicit session value is taken from? Which context? I do not have to define any session object by myself.
Implicit parameters provide a way to allow parameters of a method to be "found". This means that if a parameter value is not supplied then the compiler will search for an "implicit" value defined within scope according to resolution rules:
Variable has to be marked implicit to be considered as a candidate
Explicit definitions override implicits
Local scope is looked first
Classes companion object is searched if it exists
Scala documentation puts it this way:
First, eligible are all identifiers x that can be accessed at the
point of the method call without a prefix and that denote an implicit
definition or an implicit parameter. Second, eligible are also all
members of companion modules of the implicit parameter’s type that are
labeled implicit.
It seems there's also a bunch of edge cases and not a whole lot of good documentation so I don't encourage to go crazy with implicits or you might be in for a surprise.
My question is: Where implicit session value is taken from? Which
context? I do not have to define any session object by myself.
In this example, implicit session is a formal parameter declaration for the function literal it begins. Thus the actual value is supplied by the code in readOnly that will invoke that function in carrying out its operation.
Making it implicit here means the code in the function body (which I presume to be a Slick query) wants / needs / prefers an implicit parameter for the sake of notational convenience. (Implicit formal parameters may always have their actual parameter passed explicitly).
Incidentally, the inner braces are unnecessary and should be omitted.

Slick threadLocalSession vs implicit session

I encountered this problem while posting this question: Slick Write a Simple Table Creation Function
I am very new to Slick and concurrency, knowing only the basics. I worked with JDBC before, but in there you have to manually open a session and then close it. Nothing goes beyond that, and there is very little automation (at least I didn't have to make automated process).
However, I get confused with Slick session. In the tutorial, the example "Getting Started" encourages people to use threadLocalSession:
// Use the implicit threadLocalSession
import Database.threadLocalSession
http://slick.typesafe.com/doc/1.0.0/gettingstarted.html
The original recommendation is:
The only extra import we use is the threadLocalSession. This
simplifies the session handling by attaching a session to the current
thread so you do not have to pass it around on your own (or at least
assign it to an implicit variable).
Well, I researched a bit online, and some people suggest not to use threadLocalSession and only use implicit session. Some suggest using threadLocalSession.
One reason to support implicit session is that "makes sure at compile time that you have a session". Well, I only have two questions:
When people use "thread", are they referring to concurrency? Slick/JDBC data storage was handled through concurrency?
Which way is better? Implicit or threadLocalSession? Or when to use which?
If it is not too much to ask, I read the syntax of {implicit session:Session => ...} somewhere in my Scala book, and I forgot where it was. What's this expression?
A threadLocalSession is called this way because it is stored in a "thread local variable", local to the current execution thread.
As of Slick 2, we recommend not to use threadLocalSession (which is now called dynamicSession) unless you see a particular need for it and are aware of the disadvantages. threadLocalSession is implicit, too, by the way. The problem is, that a threadLocalSession is only valid at runtime when a withSession (in Slick 2.0 withDynSession) call happened somewhere down the call stack. If it didn't the code still compiles but fails at runtime
{implicit session:Session => ...} is a function from (the explicitly annotated type) Session to ..., where the session is available as an implicit value in ... . In db.withSession{ implicit session:Session => ... }, db creates a session, passes it into the closure handed to withSession. In the closure body ..., the session is implicit and can implicitly used by .list calls, etc.

Understanding call by name with currying in Scala

I am trying to understand database connections in Scala using the default Anorm library in play framework. Play has a sample example "Computer Database" where one of the functions tries to retrieve a computer from the DB:
DB.withConnection { implicit connection =>
SQL("select * from computer where id = {id}").on('id -> id).as(Computer.simple.singleOpt)
}
If I look at the function signature of withConnection it is this:
def withConnection [A] (block: (Connection) ⇒ A)(implicit app: Application): A
Execute a block of code, providing a JDBC connection. The connection and all created statements are automatically released.
**block** Code block to execute.
My question is how to map each value of function call to function definition? For example what is A (is it the whole SQL query, but what does the return type mean then?). What the implicit app in this case? Where is it defined?
admittedly this example is confusing, since it combines several language features
type parameters (generics)
currying (=two argument lists)
anonymous inline function (function block)
implicit arguments (which are picked up from the context)
As always, when matters start to become complicated, lets' sort it out one by one
(1) A is a type parameter. This is replaced by a suitable type on each invocation of the function. Since A is mentioned at two locations in the argument list and in the return type, this means that whatever type you use, the result type of the passed-in function block will be the same than the overall return type. You could explicitly define A when using the function, but typically you can leave it out, since the compiler can infer the actual type used.
(2) currying is easy to understand. This function here just has two parameter lists. Which means you can apply this function in several steps. First apply the left parameter list:
def myBlock(connection:Connection):SQL =
SQL("select ......" .....
val pf = DB.withConnection(myBlock)
Question: what kind of Object is pf ? what is ists type?
Answer: it is a function, taking one argument, an Application object
Thus the type of pf would be Application => SQL since in the first, partial application of the function, we just passed in another function with return type SQL, thus type parameter A is inferred to be SQL
(3) but in the code above, we've defined the function myBlock in a conventional fashion, and we gave it explicitly the name "myBlock". This isn't necessary. We can define the same function just inline, using the block syntax.
(4) and now the confusing, "magic" part, the implicits. This is a very special feature of Scala, where the compiler allows you to omit some values, or arguments (in our case). You may not omit arbitrary arguments, but only arguments marked as implicit. When you do so, the compiler doesn't immediately generate an error; rather it looks in the current scope, if he can find some suitable other object with the same name.
Effectively this means, that in your example, there must somehow be an value "connection" of type Connection, and there must be a value "application" of type Application. Both values must be visible somehow in the current scope -- that is, either as parameter, as value in an enclosing scope, or as value in the companion object, or you might have brought them into scope explicitly with an import statement. The purpose of this language feature is just to save you typing those obvious arguments (application and connection9 again and again