I've been using Play! Framework with Java and would like to try it out with Scala.
I've started on a Scala book but the most basic Play! sample has me completely puzzled:
def index(): Action[AnyContent] = Action { implicit request =>
Ok(views.html.index())
}
What Scala construct is Play! using here? I understand that we are defining a function that returns an Action with a generic parameter AnyContent. But the next part has me puzzled. What does the assignment mean in this context?
If I go to definition of Action[AnyContent] it's defined as trait Action[A] extends EssentialAction { ... }
If I go to the definition of Action after equals it's defined as:
trait BaseController extends BaseControllerHelpers {
/**
* The default ActionBuilder. Used to construct an action, for example:
*
* {{{
* def foo(query: String) = Action {
* Ok
* }
* }}}
*
* This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
*/
def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
}
Note: I'm interested in the Scala construct that's used I don't care what Play! is actually doing here which I kind of understand.
You are essentially calling Action.apply(), which is defined here in ActionBuilder. The first and only parameter of the apply() function being the function request => Ok(...).
Related
I am a novice of Play Framework. When I learn it on its webpages. I found some code like this:
import play.api.mvc._
def logging[A](action: Action[A]) = Action.async(action.parser) { request =>
logger.info("Calling action")
action(request)
}
I checked its document and there is a function async in ActionBuilder.
How does Action.async works? It seems there is no object Action in play.api.mvc
object Action has been removed in Play 2.8 by Remove deprecated play.api.mvc.Action #9288, and has been replaced by BaseController.Action method which refers to injected controllerComponents.actionBuilder rather than the global objects
/**
* ...
* This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
*/
def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
Notice how, perhaps unconventionally, the method name begins with an uppercase letter. My assumption is this was done to maintain familiar usage
def foo(query: String) = Action {
Ok
}
I am trying to learn scala. I know how to write a function. This is how I write a function.
def test_function: Unit = {
println("This is just a test")
}
But then I started learning playframework. This is how they write a function in controller in play.
def test_function: Unit = Action{
println("This is just a test")
}
My question is what is this Action doing before the curly braces? What is it called? How can I write my own? I hope I have made my question clear. Thanks in advance.
You can get this kind of behavior by defining an apply method on an object called Action:
object Action {
def apply(block: => Unit): Unit = {
println("before")
block // do the action in the block
println("after")
}
}
Then both of these:
Action { println("hi") }
Action(println("hi"))
Produce this:
before
hi
after
The thing in braces after Action is just the argument to the apply method. Scala allows either parentheses or braces, but using braces allows you to put multiple statements in:
Action {
println("a")
println("b")
}
yields:
before
a
b
after
Action is a trait (play.api.mvc.Action). Essentially it represents this type: play.api.mvc.Request => play.api.mvc.Result (doc1, doc2).
In your case you are using Action {...} which is equivalent to Action(...) and converted by compiler to Action.apply(...) call. If you check source code you'll see the apply method signatures defined not only on the Action trait and it's companion object, but also in here:
/**
* Provides helpers for creating `Action` values.
*/
trait ActionBuilder[+R[_]] extends ActionFunction[Request, R]
In your case you are not taking any request and not producing any response, so essentially your Action is a function call of a form apply(block: => Result) where Result is thrown away since you define return type of your function as Unit.
Action supports many ways you can handle its body (including Futures) so pick the right apply method to cover your needs.
You can extend Action if you need to since it's not a final implementation. Here is an example:
case class Logging[A](action: Action[A]) extends Action[A]
Action is basically a function alias of the shape play.api.mvc.Request => play.api.mvc.Result. When you see Action { }, you are actually seeing apply function of the companion object of that type and are passing a body that should provide that Request => Result function.
The companion object has roughly the shape of:
object Action {
def apply(f: Request => Response): Action = ...
}
so that when you call Action { ... }, the { ... } is that function that will be executed when the action is invoked.
In your example, println("This is just a test") serves as the provider of the Result.
I am trying to use the new Scala 2.10 implicit class mechanism to convert a java.sql.ResultSet to a scala.collection.immutable.Stream. In Scala 2.9 I use the following code, which works:
/**
* Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
* traversed using the usual methods map, filter, etc.
*
* #param resultSet the Result to convert
* #return a Stream wrapped around the ResultSet
*/
implicit def resultSet2Stream(resultSet: ResultSet): Stream[ResultSet] = {
if (resultSet.next) Stream.cons(resultSet, resultSet2Stream(resultSet))
else {
resultSet.close()
Stream.empty
}
}
I can then use it like this:
val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.map {
row => /* ... */
}
The implicit class that I came up with looks like this:
/**
* Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
* traversed using the usual map, filter, etc.
*/
implicit class ResultSetStream(val row: ResultSet)
extends AnyVal {
def toStream: Stream[ResultSet] = {
if (row.next) Stream.cons(row, row.toStream)
else {
row.close()
Stream.empty
}
}
}
However, now I must call toStream on the ResultSet, which sort of defeats the "implicit" part:
val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.toStream.map {
row => /* ... */
}
What am I doing wrong?
Should I still be using the implicit def and import scala.language.implicitConversions to avoid the "features" warning?
UPDATE
Here is an alternative solution that converts the ResultSet into a scala.collection.Iterator (only Scala 2.10+):
/*
* Treat a java.sql.ResultSet as an Iterator, allowing operations like filter,
* map, etc.
*
* Sample usage:
* val resultSet = statement.executeQuery("...")
* resultSet.map {
* resultSet =>
* // ...
* }
*/
implicit class ResultSetIterator(resultSet: ResultSet)
extends Iterator[ResultSet] {
def hasNext: Boolean = resultSet.next()
def next() = resultSet
}
I don't see a reason here to use implicit classes. Stick to you first version. Implicit classes are mainly useful (as in "concise") to add methods to existing types (the so called "enrich my library" pattern).
It is just syntactic sugar for a wrapper class and an implicit conversion to this class.
But here you are just converting (implicitly) from one preexisting type to another preexisting type. There is no need to define a new class at all (let alone an implicit class).
In your case, you could make it work using implicit classes by making ResultSetStream extend Stream and implementing as a proxy to toStream. But that would really a lot fo trouble for nothing.
In a Play Framework project, I have controllers for handling REST request, an example would be:
object AddressBean extends Controller with RestTrait{
def list = Action {
val list = Addresses.findAll()
Ok(Json.toJson(list.map(s => Json.toJson(s)(AddressJson.addressWrites))))
}
def create = Action {
Ok("")
}
}
(please note that I just put OK("") to compile, I have to implement them, like I implemented list method).
I want to define a trait for all these REST classes to implement the same methods and I started like:
/**
* Define an interface for all of our REST classes.
*/
trait RestTrait extends Controller{
/**
* List entities.
*/
def list
/**
* Create entity. Get entity from request.body
*/
def create
//and so on
}
The issue is that I receive a warning saying Unit does not take parameters so I understand that my methods from trait should have an Action return type so I end up defining them like:
/**
* Define an interface for all of our REST classes.
*/
trait RestTrait extends Controller{
/**
* List entities.
*/
def list = Action{
Ok("")
}
/**
* Create entity. Get entity from request.body
*/
def create = Action{
Ok("")
}
//and so on
}
Isn't there any way to avoid defining methods in trait like this? Because then I have to use override in my classes. I mainly want to implement not override those methods...
Abstract methods without a return type will return Unit, so all you have to do is to add return type of Action[AnyContent] to your methods.
trait RestTrait extends Controller{
/**
* List entities.
*/
def list:play.api.mvc.Action[play.api.mvc.AnyContent]
/**
* Create entity. Get entity from request.body
*/
def create:play.api.mvc.Action[play.api.mvc.AnyContent]
//and so on
}
Action is in fact a singleton object that accepts a function which returns a Result.
object Action extends java.lang.Object with scala.ScalaObject {
...
def apply(block : scala.Function1[play.api.mvc.Request[play.api.mvc.AnyContent], play.api.mvc.Result]) : play.api.mvc.Action[play.api.mvc.AnyContent]
def apply(block : => play.api.mvc.Result) : play.api.mvc.Action[play.api.mvc.AnyContent]
}
I'm writing a ServletUnitTest trait in Scala to provide a convenience API for ServletUnit. I have something like the following in mind:
/**
* Utility trait for HttpUnit/ServletUnit tests
*
* #param [T] Type parameter for the class under test
*/
trait ServletUnitTest[T <: HttpServlet] {
/**
* Resource name of the servlet, used to construct the servlet URL.
*/
val servletName: String
/**
* Servlet class under test
*/
implicit val servletClass: Manifest[T]
/**
* ServletUnit {#link ServletRunner}
*/
sealed lazy val servletRunner: ServletRunner = {
val sr = new ServletRunner();
sr.registerServlet(servletName, servletClass.erasure.getName);
sr
}
/**
* A {#link com.meterware.servletunit.ServletUnitClient}
*/
sealed lazy val servletClient = servletRunner.newClient
/**
* The servlet URL, useful for constructing WebRequests
*/
sealed lazy val servletUrl = "http://localhost/" + servletName
def servlet(ic: InvocationContext) = ic.getServlet.asInstanceOf[T]
}
class MyServletTest extends ServletIUnitTest[MyServlet] {
val servletName = "download"
// ... test code ...
}
This code doesn't compile as written, but hopefully my intent is clear. Is there a way to do this (with or without Manifests)?
While researching this topic, I found about a solution in this scala-list post by Jorge Ortiz, which did the trick for me, and is simpler than Aaron's.
In essence, his solution is (paraphrasing):
trait A[T] {
implicit val t: Manifest[T]
}
class B[T: Manifest] extends A[T] {
override val t = manifest[T]
}
(I'm ignoring the OP request to be 2.7.7 compatible as I'm writing this in 2011...)
For now, Scala represents traits as interfaces so this technique will work. There are some problems with this approach to implementing traits, however, in that when methods are added to a trait, the implementing class will not necessarily recompile because the interface representation only has a forwarding method pointing to another class that actually implements the method concretely. In response to this there was talk earlier this year of using interface injection into the JVM at runtime to get around this problem. If the powers that be use this approach then the trait's type information will be lost before you can capture it.
The type information is accessible with the Java reflection API. It's not pretty but it works:
trait A[T]{
def typeParameter = {
val genericType = getClass.getGenericInterfaces()(0).asInstanceOf[ParameterizedType]
genericType.getActualTypeArguments()(0)
}
}
class B extends A[Int]
new B().typeParameter -> java.lang.Integer
Some invariant checks should be added I've only implemented the happy path.
I found a solution that works, but it's pretty awkward since it requires the test class to call a method (clazz) on the trait before any of the trait's lazy vals are evaluated.
/**
* Utility trait for HttpUnit/ServletUnit tests
*
* #param [T] Type parameter for the class under test
*/
trait ServletUnitTest[T <: HttpServlet] {
/**
* Resource name of the servlet, used to construct the servlet URL.
*/
val servletName: String
/**
* Servlet class under test
*/
val servletClass: Class[_] // = clazz
protected def clazz(implicit m: Manifest[T]) = m.erasure
/**
* ServletUnit {#link ServletRunner}
*/
sealed lazy val servletRunner: ServletRunner = {
val sr = new ServletRunner();
sr.registerServlet(servletName, servletClass.getName);
sr
}
/**
* A {#link com.meterware.servletunit.ServletUnitClient}
*/
sealed lazy val servletClient = servletRunner.newClient
/**
* The servlet URL, useful for constructing WebRequests
*/
sealed lazy val servletUrl = "http://localhost/" + servletName
def servlet(ic: InvocationContext) = ic.getServlet.asInstanceOf[T]
}
class MyServletTest extends ServletIUnitTest[MyServlet] {
val servletName = "download"
val servletClass = clazz
// ... test code ...
}