Play-Scala: How to use method overloading In actions? - scala

I want to make tow action with different Input and make one able to call the other:
def showQuestion(questionId :Long)=Action{
Redirect(routes.Application.showQuestion(Question.find.byId(questionId)))
}
def showQuestion(question :Question)=Action{
Ok(views.html.show(question))
}
I tried the above but no luck. the compiler complaining:
found : models.Question
[error] required: Long
[error] Redirect(routes.Application.showQuestion(Question.find.byId(questionId)))
referring to first one.

I think that you are missing something.
In your routes file, you can't map an Url to the second Action:
GET /question/:id controllers.Question.showQuestion(id: Long)
GET /question/:question controllers.Question.showQuestion(question: Question) // <== how to map the "question" in the Url ???
So why not something like that (in this case, it is not really relevant to use two methods) :
def showQuestion(questionId: Long)=Action{
showQuestion(Question.find.byId(questionId))
}
private def showQuestion(question: Question)=Action{
Ok(views.html.show(question))
}

It's not a direct answer, however there's some point worth of thinking:
Main task for the router is translation and type-validation of params from request to function's args, so it's definitely better use some common types such as String, Int, Bool etc, to identify the objects in DB instead trying to pass whole objects through the router. Actually your first route does that properly.
I can't find any good reason for using two separate actions for finding the object and rendering the template (with object found in other action). What's more, you are trying to do that by Redirect, so it creates two requests, it's redundant! You should just delete second route and use one action:
GET /question/:id controllers.Question.showQuestion(id: Long)
def showQuestion(questionId: Long)=Action{
Ok(views.html.show(Question.find.byId(questionId)))
}
If you really, really want to split it to two separate functions, use sample of #nico_ekito, I think that you can delete second route in such case as well.
If in future you will want to overload function... better don't do it :) Overloading is fine, when you have static method available for usage in many places and it can differ with numer of arguments etc. Most probably it will be just more comfortable to work with different names of actions (even if routes will be similar) :
GET /question/:id controllers.Question.showById(id: Long)
GET /question/:name controllers.Question.showByName(name: String)
// so finally in the view you can use it just as:
<a href='#routes.Question.showById(item.id)' ...
<a href='#routes.Question.showByName(item.name)' ...

Related

PathBindable For Multiple Path Parameters In Play

I read this doc on PathBindable.
If I have a route like this:
GET /user/:user/posts/:postId controllers.BinderApplication.post(user: scalaguide.binder.models.Post)
How would I be able to capture both parameters in the Post object.
The post class would look something like this
case class Post(postId: Long, userId: Long)
I know that I can use QueryStringBindable, but I'm wondering if there's a way to use path parameters as well.
In this case, good practice will be an action composition or just an action.
routes:
GET /user/:userId/posts/:postId controllers.HomeController.post(userId: Long, postId: Long)
controller:
def post (postId: Long, userId: Long) = Action{
val user = Post(postId, userId) //some massive operation, could be async, then use Action.async
Ok(user.toString())
}
To construct Post, you will need to get user and the post id; it seems like a pretty massive operation. Play bind routes on the IO thread, so you are going to block all requests by doing a massive operation in this place.
Documentation:
In this example findById method is invoked to retrieve User instance;
note that in real world such method should be lightweight and not
involve e.g. DB access, because the code is called on the server IO
thread and must be totally non-blocking.
You would therefore for example use simple objects identifier as path
bindable, and retrieve the real values using action composition.
And some thread with advice from Greg Methvin (Lightbend engineer): https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/play-framework/b1fF2EdmCJ8/F2mX1EflJAAJ
Still, if you want to do such trick, you can use String Interpolating Routing DSL

How can I access a form from value in a Play Framework 2 template?

I am only able to access a form value in my Play Framework 2 template like this:
#eventForm("options[0].safeToDelete").value.toString()
But I need to also be able to access it from within a method in the template, like this:
optionFields(option: Field)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) = {
#option("safeToDelete").value.toString()
}
#optionFields(eventForm("options[0]"))
The first example returns true.
The second one returns Some(true).
How can I get the second one to return true?
In Scala Option[T] is a different way of handling null objects.
It has two subtypes - Some[T] and None. One of the many ways you can handle this is as below,
#option("safeToDelete").value.getOrElse(false).toString
Read through for more.. http://www.tutorialspoint.com/scala/scala_options.htm

Serialize Function1 to database

I know it's not directly possible to serialize a function/anonymous class to the database but what are the alternatives? Do you know any useful approach to this?
To present my situation: I want to award a user "badges" based on his scores. So I have different types of badges that can be easily defined by extending this class:
class BadgeType(id:Long, name:String, detector:Function1[List[UserScore],Boolean])
The detector member is a function that walks the list of scores and return true if the User qualifies for a badge of this type.
The problem is that each time I want to add/edit/modify a badge type I need to edit the source code, recompile the whole thing and re-deploy the server. It would be much more useful if I could persist all BadgeType instances to a database. But how to do that?
The only thing that comes to mind is to have the body of the function as a script (ex: Groovy) that is evaluated at runtime.
Another approach (that does not involve a database) might be to have each badge type into a jar that I can somehow hot-deploy at runtime, which I guess is how a plugin-system might work.
What do you think?
My very brief advice is that if you want this to be truly data-driven, you need to implement a rules DSL and an interpreter. The rules are what get saved to the database, and the interpreter takes a rule instance and evaluates it against some context.
But that's overkill most of the time. You're better off having a little snippet of actual Scala code that implements the rule for each badge, give them unique IDs, then store the IDs in the database.
e.g.:
trait BadgeEval extends Function1[User,Boolean] {
def badgeId: Int
}
object Badge1234 extends BadgeEval {
def badgeId = 1234
def apply(user: User) = {
user.isSufficientlyAwesome // && ...
}
}
You can either have a big whitelist of BadgeEval instances:
val weDontNeedNoStinkingBadges = Map(
1234 -> Badge1234,
5678 -> Badge5678,
// ...
}
def evaluator(id: Int): Option[BadgeEval] = weDontNeedNoStinkingBadges.get(id)
def doesUserGetBadge(user: User, id: Int) = evaluator(id).map(_(user)).getOrElse(false)
... or if you want to keep them decoupled, use reflection:
def badgeEvalClass(id: Int) = Class.forName("com.example.badge.Badge" + id + "$").asInstanceOf[Class[BadgeEval]]
... and if you're interested in runtime pluggability, try the service provider pattern.
You can try and use Scala Continuations - they can give you the ability to serialize the computation and run it at later time or even on another machine.
Some links:
Continuations
What are Scala continuations and why use them?
Swarm - Concurrency with Scala Continuations
Serialization relates to data rather than methods. You cannot serialize functionality because it is a class file which is designed to serialize that and object serialization serializes the fields of an object.
So like Alex says, you need a rule engine.
Try this one if you want something fairly simple, which is string based, so you can serialize the rules as strings in a database or file:
http://blog.maxant.co.uk/pebble/2011/11/12/1321129560000.html
Using a DSL has the same problems unless you interpret or compile the code at runtime.

MEF: metadata seem to override interface when using GetExports

I'm building a MEF-based plugin-centric WPF application and I'm facing an issue with GetExports, maybe it's just my ignorance but I find an odd behaviour. I have a number of exported parts, all derived from 2 different interfaces (let's name them A and B), but all marked with the same metadata attribute X. So I have code like:
[Export(typeof(A))]
[TheXAttributeHere...]
public class SomePart1 : A { ... }
for each part, and the same for classes implementing B:
[Export(typeof(B))]
[TheXAttributeHere...]
public class SomePart2 : B { ... }
Now, when I try getting all the parts implementing A and decorated by attribute X with some values, MEF returns not only the A-implementing parts, but ALSO the B-implementing parts. So, when I expect to deal with A-objects I get a B, whence a cast exception.
In the real world, interfaces are named IItemPartEditorViewModel and IItemPartEditorView, while their common attribute is named ItemPartEditorAttribute and exposes a PartType string property on which I do some filtering. My code to get parts is thus like e.g.:
var p = (from l in container.GetExports<IItemPartEditorViewModel, IItemPartEditorMetadata>()
where l.Metadata.PartType == sPartType
select l).FirstOrDefault();
When looking for IItemPartEditorViewModel whose PartType is equal to some value, I get the IItemPartEditorView instead of IItemPartEditorViewModel implementing object. If I comment out the attribute in the IItemPartEditorView object instead, I correctly get the IItemPartEditorViewModel implementing object.
Update the suggested "templated" method was used, but I mistyped it here as I forgot to change lessthan and greaterthan into entities. Anyway, reviewing the code I noticed that in the attribute I had "ViewModel" instead or "View" for the interface type, so this was the problem. Shame on me, sorry for bothering :)!
I think I'd need to see more of the code to know for sure what's going on. However, I'd suggest you call GetExports like this:
// Get exports of type A
container.GetExports<A>();
// Get exports of type B
container.GetExports<B>();
Then do your filtering on the list returned. This will probably fix the cast issues you are having. I'd also be interested in seeing the code for the custom metadata attribute. If it derives from ExportAttribute for example, that might be part of the problem.

ScalaTest: Issues with Singleton Object re-initialization

I am testing a parser I have written in Scala using ScalaTest. The parser handles one file at a time and it has a singleton object like following:
class Parser{...}
object Resolver {...}
The test case I have written is somewhat like this
describe("Syntax:") {
val dir = new File("tests\\syntax");
val files = dir.listFiles.filter(
f => """.*\.chalice$""".r.findFirstIn(f.getName).isDefined);
for(inputFile <- files) {
val parser = new Parser();
val c = Resolver.getClass.getConstructor();
c.setAccessible(true);
c.newInstance();
val iserror = errortest(inputFile)
val result = invokeparser(parser,inputFile.getAbsolutePath) //local method
it(inputFile.getName + (if (iserror)" ERR" else " NOERR") ){
if (!iserror) result should be (ResolverSuccess())
else if(result.isInstanceOf[ResolverError]) assert(true)
}
}
}
Now at each iteration the side effects of previous iterations inside the singleton object Resolver are not cleaned up.
Is there any way to specify to scalatest module to re-initialize the singleton objects?
Update: Using Daniel's suggestion, I have updated the code, also added more details.
Update: Apparently it is the Parser which is doing something fishy. At subsequent calls it doesn't discard the previous AST. strange. since this is off topic, I would dig more and probably use a separate thread for the discussion, thanks all for answering
Final Update: The issue was with a singleton object other than Resolver, it was in some other file so I had somehow missed it. I was able to solve this using Daniel Spiewak's reply. It is dirty way to do things but its also the only thing, given my circumstances and also given the fact I am writing a test code, which is not going into production use.
According to the language spec, no, there is no way to recreate singleton objects. However, it is possible to reflectively invoke the constructor of a singleton, which overwrites the internal MODULE$ field which contains the actual singleton value:
object Test
Test.hashCode // => e.g. 779942019
val c = Test.getClass.getConstructor()
c.setAccessible(true)
c.newInstance()
Test.hashCode // => e.g. 1806030550
Now that I've shared the evil secret with you, let me caution you never, ever to do this. I would try very very hard to adjust the code, rather than playing sneaky tricks like this one. However, if things are as you say, and you really do have no other option, this is at least something.
ScalaTest has several ways to let you reinitialize things between tests. However, this particular question is tough to answer without knowing more. The main question would be, what does it take to reinitialize the singleton object? If the singleton object can't be reinitialized without instantiating a new singleton object, then you'd need to make sure each test loaded the singleton object anew, which would require using custom class loaders. I find it hard to believe someone would design something that way, though. Can you update your question with more details like that? I'll take a look again later and see if the extra details makes the answer more obvious.
ScalaTest has a runpath that loads classes anew for each run, but not a testpath. So you'll have to roll your own. The real problem here is that someone has designed this in a way that it is not easily tested. I would look at loading Resolver and Parser with a URLClassLoader inside each test. That way you'd get a new Resolver each test.
You'll need to take Parser & Resolver off of the classpath and off of the runpath. Put them into a directory of their own. Then create a URLClassLoader for each test that points to that directory. Then call findClass("Parser") on that class loader to get it. I'm assuming Parser refers to Resolver, and in that case the JVM will go back to the class loader that loaded Parser to get Resolver, which is your URLClassLoader. Do a newInstance on the Parser to get the instance. That should solve your problem, because you'll get a new Resolver singleton object for each test.
No answer, but I do have a simple example of where you might want to reset the singleton object in order to test the singleton construction in multiple, potential situations. Consider something stupid like the following code. You may want to write tests that validates that an exception is thrown when the environment isn't setup correctly and also write a test validates that an exception does not occur when the environment is not setup correctly. I know, I know everyone says, "Provide a default when the environment isn't setup correctly." but I DO NOT want to do this; it would cause issues because there would be no notification that you're using the wrong system.
object RequiredProperties extends Enumeration {
type RequiredProperties = String
private def getRequiredEnvProp(propName: String) = {
sys.env.get(propName) match {
case None => throw new RuntimeException(s"$propName is required but not found in the environment.")
case Some(x) => x
}
}
val ENVIRONMENT: String = getRequiredEnvProp("ENVIRONMENT")
}
Usage:
Init(RequiredProperties.ENVIRONMENT)
If I provided a default then the user would never know that it wasn't set and defaulted to the dev environment. Or something along these lines.