When I did a bit of Play 1.2 dev, I ran into two serious annoyances.
First, static actions make for untestable code. The only way to test this in 1.2 was to do full integration tests. You can't unit test controllers/actions, which to me is a horrible "opinion" to have. Looking at the docs, 2.0 [appears] to make an attempt via the callAction helper [1], but you still can't inject dependencies via a constructor and call instance methods. Static members in static languages make testing a real pain.
Second, JSON felt like a 2nd-class citizen. Dealing with JSON in either the request or the response felt barbaric. I don't see that they've improved things. Auto binding from a JSON request to an object should exist without having to write a bunch of custom JSON serializers...doubly so for outputting json.
I can't agree more - I've been doing a non-trivial bit of scala work in the past six months, and the part that seems the most lacking to me is JSON support. Every scala JSON library I've used (spray-json, sbjson, lift-json and the like) requires you to define a concrete serializer class for every single type you would like to move across the wire. I really miss the ease of use of reflection-based parsers like Jackson. I've alleviated a bit of this by writing a generic serializer that uses Jackson under the hood, but that requires every class to use a java bean pattern, and not the more elegant scala case class (or frankly plain old scala object) patterns.
There's a project called Jerkson that is attempting to fix this, but I'd like to see all the major scala frameworks just settle on something good and simple and go from there.
Also, Play 2.0 includes Jerkson, so whatever Jerkson can do, Play 2.0 can do. They just happened to add some helper utilities that made it very similar to lift-json. So I think the community is settling on something good and simple.
I disagree on the fact that JSON is a second-class citizen. A lot of effort went into good support of JSON. But obviously, Scala and Java being statically typed languages, you can't expect to use JSON in those languages like you use them in Javascript.
The reason why everyone encourage you to do so is because typeclass serialization is much more robust that introspection. With introspection you may have runtime exceptions, but with typeclass serialization you know at compile time when something is wrong.
Also, Jerkson is included in Play 2 (that's what we use as base for the Json lib) so you can use it directly if you want introspection.
I agree about the testing. It is also really annoying that you can't run a test as a "single, isolated test". I read a few articles on Play 2.0 and Scala, but haven't come across any additions on testing. Without decent testing integrated, this framework has no real production use. I agree that it all looks nice and shiny though.
Can you elaborate more on the untestable code point, for those of us who've been spending more time on ruby lately? I find play very interesting, but it's great to hear about its warts as well.
This is the first controller I opened from their samples[1] :
public class Forums extends Application {
public static void index() {
List forums = Forum.findAll();
long topicsCount = Topic.count();
long postsCount = Post.count();
render(forums, topicsCount, postsCount);
}
...
}
You can't mock out Forum, Topic or Post. You can't inject some type of "FormRepository" or whatever pattern you want to gain some type of control. In Ruby, or most dynamic languages, this wouldn't be a problem, since a class method can (and should) be mocked. Even if a static language allows for that sort of trickery (for example, there are a couple ways to test the above in C#), it's the wrong approach. Dependencies should be injected and thus controlled. I guess you could inject using static setters, but that's just a bad workaround to what, in my opinion, is a fundamental misunderstanding of how to write testable code.
If you wanted to unit test this I'm confident you could do it using JMockit [1] without changing the code. JMockit allows you to mock just about anything (static methods, final methods, constructor invocations). The unit test might look something like:
@Test
public void checkIndexRenders()
{
final List expectedforums= new ArrayList(asList(TEST_FORUM));
new NonStrictExpections()
{
@Mocked Forum forum;
@Mocked Topic topic;
@Mocked Post post;
{
Forum.findAll(); result = expectedforums;
Topic.count(); result = 5;
Post.count(); result = 10;
}
};
Forums.index()
// your assertions ...
}
I come from a DI background, but the JMockit framework has changed my view of what untestable code is.
Apologies for the tangent, but is this considered idiomatic Java these days? As a person who knows/knew Java pretty well but has been out of the game for a few years, this code seems highly surprising. Instantiating an anonymous subclass with a static initializer to... I suppose be able to use those @Mocked annotations. Then assigning result in that anonymous initializer block, which I must assume works through black magic.
No criticism of your code example. I think figuring out how to make Java do this is very impressive. I just wonder if it's considered wise to do this sort of thing in production code?
(Edited to correct that I don't think that's a static initializer block.)
Generally this would not be done in production code. jMockit is pretty out there, syntax - wise, and the anonymous inner classes are generally discouraged in production code. In tests are generally fine though. which is why jMockit can get away with it.
Unit testing isn't really about ensuring correctness.
First and foremost, it's a design tool. Code that can't easily be unit tested is often poorly designed. The most common example in the MVC-world is a fat controller. It's hard to test any method that does too much because of all the setup that you'll have to do. If an action is doing too much, dependent on too many parts, and not very cohesive, you'll feel the pain when you try to test it.
Of course, it's just an indicator...a warning symbol. Some times method need to do a lot...sometimes they do a lot while being cohesive and not having a lot of dependencies. Ultimately, your brain is the judge, a unit test is just a tool to help measure a method's entropy.
Secondly, it's a refactoring tool. Or, put differently, it's about future correctness. Broadly speaking, in this sense, it's also documentation. At a unit test level, this is tricky...and I've struggled with it quite a bit...if you overly concern yourself with internals (using a strict mock), you'll have a brittle test which is largely focused on the current correctness. However, using loose stubs, it really can prevent the introduction of bugs without being overly brittle.
So would the appropriate approach in this case be to create IForum, ITopic and IPost interfaces and, instead of calling findAll() or count() directly on the class, call it on the interface so a class can be injected? Sorry...this is all a bit hazy to me. It's been years since I've had to deal with these sorts of concerns.
Something like that..but then the question is: how do you get the instance in there? Normally through DI (ideally at the constructor level)...but the static method screws that up.
I agree that worrying about this is silly, but such is the life of someone who uses static languages.
What you're complaining about is just the data access which happens to be used in this sample (particularly some convenience methods which aren't even necessary), which you can freely change out with any technology that you please, because it's completely orthogonal to the rest of the framework. The framework has no abstractions over or requirements for the data access framework.
Or without even changing the data access calls you could just put them behind a DAO object, which would have been injected and therefore easily replaced for testing. But that wouldn't have made the sample any clearer.
Can't you mock out the calls with something like http://code.google.com/p/powermock/? Or introduce an intermediate object? Or use Spring? Or test using groovy which i think you can redefine methods.
I am really excited about this but also a bit worried that Java will become a second class citizen for Play development.
The typesafe deal, use of SBT and other scala tools, and the overhead of maintaining docs and bindings for 2 languages all seems to point to an inevitable deprecation of Java at some point.
I partially disagree, especially with backing from Typesafe.
The "engine" benefits from Scala, as a highly concurrent and transactional heavy system. The choice of language for building MVC applications & services on that engine is left up to the developer. The 2.0 mindset, and you see this in everything is very much a best tool for the job balanced with flexibility and choice.
It's going to take a little while for a language like Scala (or any JVM based language) to fully penetrate the market. A lot of Java developers are not there yet, and by a lot, I mean most, who are we kidding. I see more shops embracing the JVM as their "stack" and the right language for the job mindset on top of that foundation. It's flexible, conservative, and forward thinking at the same time.
Play fits nicely into that space and is something that the core team appears to be mindful of. In fact, if they're smart about it, Play could end up being a bridge for Java developers interested in making the transition to Scala, at a pace that makes sense for them.
I totally agree that the best case scenario is Play 2 lowering the learning curve and providing a bridge for java devs trying to get up to speed with Scala.
I just think it will be hard to justify play2's use in java-heavy organizations if Java support is a second citizen to Scala.
I loved Play 1.2.x, I think it is the only framework that really provides a way forward for modern java web dev, and I strongly hope Play 2 keeps things moving.
> It's going to take a little while for a language like Scala (or any JVM based language) to fully penetrate the market.
By a wide margin, the overall consensus in the JVM community seems to be that Scala will probably never be more popular than it is today, which means, it will never become mainstream. Hopefully, one of Ceylon or Kotlin will succeed where Scala failed.
With that in mind, Play betting on Scala is quite a risky direction indeed.
+1 can you please backup your claim? Scala does not need to be Java popular to be usable (probably no alternative JVM lang will ever be as popular as Java - especially now that Java is evolving).
also, play is not "betting" on scala. Just because it was implemented in scala and provides a scala API that does not mean you can not use the framework from Java (or Kotlin, or Jruby etc.). If you do not care about the scala API, that's fine, use the Java API instead.
It's just that most of the curves have remained flat. Look on job boards, language rankings, github stats, or even the Scala reddit, which is a ghost town.
Taken in isolation, these numbers don't mean much but when you start putting all the evidence together, it's hard to make a case that Scala is growing at all.
There's at least as many Java developers in the Play community. The devs would certainly hear about it if any feature were supported only in Scala and I imagine you'd see community members submitting patches, etc. to remedy the situation.
I think that's the direction that they're already heading. While Java will be supported by nature, I think Scala is a better fit for the growth the framework itself.
Sorry for being "rantish", but most of the "negative" comments I'm reading around here are from people who didn't spend a single second reading the manual.
Yes, I'm not partial, I'm invested on Play, but I am because it has a wonderful documentation that makes life really easy (that plus StackOverflow).
Most of the complains in here come from people with almost no experience in it. No, a small side project of 6 hours is not "experience". You just toyed around. You can't know about the real issues or benefits related to a framework.
Please, I know this is "the internet", but in a site like Hacker News, couldn't you try to talk only about things you know?
Not much of a fan of the new Typesafe Stack. It doesn't seem to install the scala, play and akka command-line tools like the old versions did. Is there a way to get a straight Scala REPL, or does everything have to go through giter8 and sbt now?
I was aware of that, but it seems silly to have a separate installation of Scala just for the REPL when the stack includes most of the important stuff already.
I guess that I'd be better off just using the individual components instead, for now. With the new version it feels like they've switched from being a fairly plain "distribution" of Scala/Akka to more of an opinionated tool set based on giter8 and sbt. That's a pretty big jump, and I'm hoping that the lack of command-line support tools is something that's fixable once things are settled a bit.
Then are you just asking how to get a Scala REPL using sbt?
If so, you can get one by entering the command 'sbt console' in a project directory. This will give you a scala console with the added bonus that all of the files in your project will be loaded as part of the REPL's classpath.
For anyone interested in its claim of being reactive, as I was, the Play framework does not appear to support reactive programming [1].
From their samples and documentation, it looks like an event-driven server without any reactive aspects. I'm fairly sure they're mistakenly calling typical event-driven programming "reactive". This is backed up by the statements of Typesafe's CEO on the subject in an interview [2].
Which indeed is talking about stream processing. Play's stream processing uses iteratee IO to correct control inversions often suffered by networking libraries.
However, Play does not offer automatic facilities for having variables (and interface) update when other variables change, as described in the Wikipedia article. For examples of reactive programming, see Knockout, batman.js and Ember.js (all primarily client-side).
Last summer I evaluated Lift vs Play 1.x and was leaning heavily toward Play. I wrote some toy apps in each. We chose Lift only because it turned out that Play was incompatible with our Maven setup. (I have heard it has improved in 2.0 but I have not looked into it myself.)
I found Play to be fairly intuitive and it matched my mental model pretty well. It was lightweight compared to Lift and the other Java frameworks I looked at. Play 2.0 seems to have made improvements in the areas I found weak in Play 1.x. i.e. modularity, Scala support (specifically for continuations)
Lift is a fairly heavy framework, but you can ignore big parts of it if you need to. In Lift it took me a while to grasp the HTML transforming concept, partly because the documentation seemed to out of date. It felt both cumbersome and elegant at the same time. Sadly I didn't get very far on the project so I have no idea how Lift has changed/improved since then.
Today I would choose Play in a heartbeat if it fit the parameters of my project.
I find that testing has improved quite a bit since actions now return a Result object that you can inspect in your tests. It is true that you cannot inject a mock data repository, for example, but Controllers are meant to be simple HTTP response generators and you might want to make them call some domain object to perform anything complicated. You can then unit test you domain object to your heart’s content.
That way of handling io is indeed snazzy, and a port of ideas from some Haskell libs, but it's worth pointing out that on the Haskell side there's been a bit of innovation in allowing more direct style Apis for iteratee libraries
Their beta was incredibly buggy, riddled with compilation performance performance, slow load times, was really not a fun experience. I've heard they finally got development load times in check. I hope they get their deployment process a bit better then creating a zip file and having to run nohup on their start script.
It got to be pretty stable at RC3. I agree the beta was poor in a number of areas, but I've been consistently using the latest from GitHub for months now and would recommend you give it another go with this final release. They deployment story is the same, though I've filed some feature requests around this and I imagine this will be improved by the community as more people start using v2.
First, static actions make for untestable code. The only way to test this in 1.2 was to do full integration tests. You can't unit test controllers/actions, which to me is a horrible "opinion" to have. Looking at the docs, 2.0 [appears] to make an attempt via the callAction helper [1], but you still can't inject dependencies via a constructor and call instance methods. Static members in static languages make testing a real pain.
Second, JSON felt like a 2nd-class citizen. Dealing with JSON in either the request or the response felt barbaric. I don't see that they've improved things. Auto binding from a JSON request to an object should exist without having to write a bunch of custom JSON serializers...doubly so for outputting json.
[1] http://www.playframework.org/documentation/2.0/JavaFunctiona...