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]
}
Related
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(...).
I want to write something like this:
/**
* Represents a state, large or small.
*/
interface State {
/**
*
*/
val changeValue: StateChange<This> // does not compile; "This" is a keyword I made up that might reference the implementing class
}
/**
* Represents a change in a state, large or small.
*
* #param StateType The type of state that has changed
*/
interface StateChange<StateType: State>
However, as noted in my comment, I don't know the syntax for this. Is that in existance? Or must I use workarounds like forcing a State to take in itself as a generic parameter?
In case it's not apparent, I can't use val changeValue: StateChange<State> because then that makes this possible, and I don't want that:
// BAD EXAMPLE - This is what I want to avoid
class Foo: State { val changeValue: StateChange<Bar> = Bar().changeValue }
class Bar: State { val changeValue: StateChange<Foo> = Foo().changeValue }
You can use a class with a recursive upper bound for this:
interface State<T : State<T>> {
val changeValue: StateChange<T>
}
interface StateChange<StateType: State<StateType>>
Now this code will no longer compile:
class Foo: State<Foo> { val changeValue: StateChange<Bar> = Bar().changeValue }
class Bar: State<Bar> { val changeValue: StateChange<Foo> = Foo().changeValue }
The following code:
trait TestMainArgs extends App {
println(s"args are: $args") // I need to have a generic main in trait which refers to args...
}
object MyRealMainObj extends TestMainArgs {
// I do not want to call the generic main from objects this would mean I would need to call them from every object which extendfs TestMainArgs
}
prints:
args are: null
While the following:
trait TestMainArgs extends App {
}
object MyRealMainObj extends TestMainArgs {
println(s"args are: $args")
}
prints:
args are: [Ljava.lang.String;#f82f98
So how can I access args from the trait?
I want to put the logic of the "main" only in the super trait and I don't want code duplication like calling from every object which extends app the super main, is there any way to achieve that?
Another option that is also deprecated is to override main:
trait TestMainArgs extends App {
override def main(args: Array[String]) {
println(s"args are: ${args(0)} from test")
super.main(args)
}
}
The problem is that the way traits are compiled, the constructor is triggered before the main object, which is where args is set. There appears to be no non-deprecated means to do this...
The answer lies in looking at both DelayedInit and App in the Scala source. The real gem lies in the doc comment at the start of DelayedInit:
Example:
* {{{
* trait Helper extends DelayedInit {
* def delayedInit(body: => Unit) = {
* println("dummy text, printed before initialization of C")
* body // evaluates the initialization code of C
* }
* }
*
* class C extends Helper {
* println("this is the initialization code of C")
* }
*
* object Test extends App {
* val c = new C
* }
* }}}
*
* Should result in the following being printed:
* {{{
* dummy text, printed before initialization of C
* this is the initialization code of C
* }}}
So, just extend DelayedInit, follow the warnings you see in App (specifically, don't override args in your extending class), and you should be able to access them just as App does:
#deprecatedOverriding("main should not be overridden", "2.11.0")
def main(args: Array[String]) = {
this._args = args
//other stuff goes here as you like
}
However, if you do it like this, be aware that it is deprecated, like it says there, so you run the risk of losing the functionality in future versions of Scala.
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.
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 ...
}