Discuss New Concept,New Technic,New Tools, Including EAI,BPM,SOA,Tibco,IBM MQ,Tuxedo, Cloud,Hadoop,NoSQL,J2EE,Ruby,Scala,Python, Performance,Scalability,Distributed,HA, Social Network,Machine Learning.

Arch-Webapp

Oct 032012
 
 [repost ]Should I use Play or Lift for doing web development in Scala?  October 3, 2012  Posted by on October 3, 2012 at 11:34 pm Arch-Webapp, Lift, Play Tagged with: , ,  No Responses »

original:http://stackoverflow.com/questions/3670237/should-i-use-play-or-lift-for-doing-web-development-in-scala

 

Question:

I’m stuck on whether I should focus on Play or Lift for doing web development in Scala.

Play looks very polished. The Scala-specific tutorial looks amazing. Furthermore, since I’ve been coding in MVC frameworks for a long time, it looks super familiar. However, it doesn’t look like it can easily accomplish all the brilliant things that Lift can do. For instance, I can’t find anywhere where it mentions Comet or Jetty Continuations. Furthermore, I kind of like the “View First” methodology in Lift because instead of using one controller, it lets me use a ton of snippets to piece together a page.

Lift looks brilliant, but leaves me with a lot of questions unanswered. Being highly stateful looks like it opens up a lot of possibilities, but I wonder how it’ll turn out in practice. The book on Lift is a bit of a mess, and so is the wiki. The “Getting Started” page is badly formatted and is no match for Play’s tutorial.

Does Play support Jetty Continuations?

Is it painful to get started with Lift doing normal web application development?

How does Lift’s statefulness work out in practice? How do you cope with web servers going down in Lift? If I’m using Lift, and I push a new version of my code on a daily basis, does that mean I have to restart the application, and does that mean everyone’s session gets wiped out?

Does Lift’s statefulness actually make it easier to code?

What happens if someone messes around with the back button in Lift? What happens if a user is bouncing back and forth between several tabs?

Thanks, guys!

 

Best Answer:

I’ve now used both on moderate sized projects (each fairly traditional Web 1 apps). Lift was the first, and definitely had the impressive flash-to-bang of having the rest of my team come back from lunch and be amazed that the full, pretty, site was already up (that’s a default nav bar and little else when you look under the covers btw).

After that, though, we very quickly had to dive into the source to try to work db access out. There’s an ORM shipped with Lift which I found to be so inaccessible that I eventually gave up on it. And the source is very idiomatic scala, which is either good or bad depending where on the curve you’re currently sitting. There were several pieces of code that just had us scratching our heads and saying “But this is all just voodoo. Where did the CODE happen?”

I’ll try to edit this soon with specific examples, but it might be quite off topic and I’m worried it would add fuel to the fire of scala being too hard for normal people (it isn’t at all, but Pollack’s code probably is. Too hard for me anyway).

Play, on the other hand, didn’t have a huge scaffolding productivity peak upfront. But the error reporting and the xml literal integration meant that it only took a few hours to catch up to the initial gifted productivity that Lift gave.

By the way, “xml literal integration”, just in case someone runs off to google it, just means this:

 action.html: <div id="templatingContainer">   #{verbatim}     ${xmlVariable}   #{/verbatim} </div> codeBehind.scala:   def action={     val xmlVariable = <span>literal</span> % new xml.UnprefixedAttribute("class","something",xml.Null)     Template(xmlVariable)   } 

Now obviously I’ve left some of the scaffolding out – codeBehind.scala should really have a surrounding object extending Controller, etc. On the other hand I HAVE left in my biggest pet peeve (Edit: This may no longer be true with Scala 2.8) with Scala in either context (minimized by strict enforcement of separate tiers) – that you can’t write this literal:

<div class="something">content</div> 

Because class is a keyword. By all means write the implicit conversation, but it’s still a pain point for me.

The major differentiating factors for me are:

  • Error reporting. Play wins this hands down. It’s simply the best error reporting I’ve ever seen.
  • Brilliant hot code reloading (although your libs won’t be picked up until restart – slight pain point until you realise what’s going on – can be tricky when you’re also struggling with syntax). Play won here too.
  • Javascript – with Play you really don’t have any options but to do traditional postbacks. Lift has utterly beautiful functional tricks going on that let you inline an entire logic cycle, abstracting out the fact that there’s an HTTP request cycle in the middle.

I find Play to be sufficiently documented. Specifically, they’ve rewritten their (quite comprehensive) tutorial to be up to date with the Scala module and the 1.1 release which is a welcome relief.

On the other hand if I were to try to put a realtime app onto the web (and we get fairly frequent requests to drop our stylus based WPF app into a browser so one of these days it’s coming) I would definitely go straight to Lift; it’s super powerful with a few points of clunkiness. (Also, it might make a lot more sense now that we’ve all scalaed a bit more).

But if you’re after MVC (dare I say PHP++) go with Play.

They’re both beautiful, and absolutely differently purposed.

Thanks in advance to everyone who comes and improves on this answer. I think this is an important question to hash out in public, because I’d love to see Scala itself more widely adopted.

Answer:

Akka + Play! and you have Comet + REST + Presentation layer + scalability

Answer:

Having not programmed web apps for years, I am just now looking for a framework to help me get back in the game. I have discovered how AWESOME scala is, so I looked at Lift first.

The documentation is horrid. You’re expected to know Maven/SBT and none of the tutorials seems complete or accurate. I found “Exploring Lift” and the /prerelease/ of “Lift in Action” and both had some issues with clarity, in my opinion.

So, I looked at Play. The Scala support is not native, but it’s getting better (so I hear). I started working with Play using Java, since I know some Java and the documentation is tailored to it (The Scala project directory structure is a bit different).

Perhaps knowing the framework now will allow me to “get” Play’s scala version easier.

Great thing about Play:

  • Terrific Java documentation
  • Hot reloading
  • Error messages
  • Easy to ‘get’

IMO. Check it out; you’ll like it. Start with Java then look back at it with Scala.

Answer:

To specifically address some of the questions about Lift:

1) Is it painful to get started with Lift doing normal web application development?

If by “Normal” you mean MVC and Hibernate over RDBMS, yes. It’s more painful to do those in Lift than in Play. But that’s more or less the last of the pain you’ll experience, in my opinion. If you can manage to sketch your app in without needing to fall back on that plumbing, and leave those for later when you try to scale (both code and utility wise) up, you’ll find Lift to be incredibly fast and versatile.

2) How does Lift’s statefulness work out in practice? How do you cope with web servers going down in Lift? If I’m using Lift, and I push a new version of my code on a daily basis, does that mean I have to restart the application, and does that mean everyone’s session gets wiped out?

Yes, you would need to restart the application. Yes, that means that everyone’s session get wiped out. But that’s not necessarily disastrous. The client side javascript will continue to try to reconnect for a few minutes, and I find that it will almost always catch the rebooted application, rehandshake, refresh and be back in a usable state. This relies on your application being careful about constantly persisting its state and being able to infer location from that, which in a stateless paradigm is ubiquitous, and in a stateful paradigm is only necessary to enable this sort of hot reloading behaviour.

I’m not trying to diminish this cost, it’s a drawback. Stateful apps find it more difficult to cope with server reboot, when the session is sticky and tied to that server, than a stateless app which is storing state in an independent persistence store.

3) Does Lift’s statefulness actually make it easier to code?

Yes. Yes, it absolutely does. I’ve been frank about the inconveniences posed by a stateful model, in the first 2 answers. But here’s the payoff. Stateful behaviour is easy to code, and scales securely and simply to code complex interactions. Here’s an example, which I hope doesn’t get muddied by the inherent complexities of the Scala language (this is from a real world project):

private def inviteUser(group:Group) = {
    a(() =>{
      SpamServer ! Spam(
        self=>
          List(
            Text("Who would you like to invite?"),
            UserInformation.findAll.map(user=>
              a(()=>{
                self.done
                GroupServer ! GroupInvite(currentUser.is,user.name.is,group.name)
                Call("pendingInvitation",user.name.is)
              }, <div>{user.name}</div>))),true)
      Call("buildingUserlist")
    }, Text("Invite"))
  }

Explanation: Emit a button labelled “Invite”. That button, when clicked, calls some javascript to tell me that we’re calculating who we could invite. When we’ve calculated it, we pop up a labelled, cancellable dialog, which lists all relevant users. Each user name listed is a link, which when clicked will: Close the dialog. Call a javascript function, implementation unspecified (and decoupled), to tell me in a designer-friendly way that I have invited the user, and am waiting for them to accept. Send an invitation to the selected user, specifying who I am and which group I want them to join. That user receives the invitation without needing to poll or refresh, and will be presented with their response options using similar code to this.

The two pieces of javascript I pointed to but did not specify are both trivial, and completely view oriented (they do not participate in logic, they’re just fades and animations and stuff, to keep it feeling snappy). This markup is spliced into a designer-friendly template via CSS selectors, providing a perfectly natural collaboration between designer and developer.

There is no logic in the view, and there is no view creeping into the logic.

It’s not at all MVC, but it does provide me with a succinct, centralized way to express quite complicated and stateful logic.

4) What happens if someone messes around with the back button in Lift? What happens if a user is bouncing back and forth between several tabs?

If the application is presenting a Comet view (so, enabling real-time server push), that view takes responsibility for a piece of the screen’s real estate. The component underlying it will ensure that the right data is always on the page, without the developer having to think too hard about update protocols etc. The developer can just call reRender and have it newly there, or can do a more specific approach by emitting update Javascript. The server will push those replacement and update snippets without the page needing to ask.

The component, which lives serverside, exists in the same state on all viewing pages. Thus, one user can modify it and it will automatically reflect those changes through to everyone. This is very powerful, and saves an awful lot of synchronization code. But it’s also not the only way you can identify that component – if you choose to have it vary per user, you give it a more precise identity than its type (you give it a type and a name). If you choose to have it vary per tab, you have each page that pulls it up request it with a uniquely generated name. This ensures that the instances always different, and share no state.

Between those three possibilities, all the back/forth/new tab options are covered. Handling this case is completely under the developer’s control. (I find that the most common state by far is that you want the component to look the same on every viewing screen, regardless of refresh or open tabs. For example, a stock ticker, a status update, a message of the day… This is what you will get by simply using the Class of the component as its identity).

I hope this gives some idea of Lift’s capabilities and constraints.

Answer:

Lift makes better use of Scala’s language features, whereas Scala support feels like an afterthought in Play. Lift has much more momentum within the Scala community. Play however definitely has the edge when it comes to prototyping new apps quickly.

Performance can be a problem with Play. The framework adds a lot of machinery around your fields and methods, and these ‘enhancers’ can slow your code down and even create bugs and incompatibilities with existing code (e.g. http://play.lighthouseapp.com/projects/57987/tickets/387-incompatibility-with-antlr-parsers); just something to be aware of.

Answer:

I used lift as the initial framework for my project, it is a “view first” framework that differs tremendously from most MVC frameworks like Rails.

The following points are what drove me away from lift:

  1. The way lift obtrude javascript is really a pain in the ass.
  2. Lacks of document. the exploring lift site is still in progress and the wiki is piled with “//TODO” lists.
  3. It’s designer friendly, however, I’m mostly a developer other than a designer.

My point is, if you’ve used something like rails before, go for Play!, you’ll find home there.

Answer:

I’ve only touched Lift once so I can’t offer a comparison, but here are my $0.02 on Play!.

I spent the summer using Play! (mostly sans-scala) on the job, and will likely be starting another Play! project soon, this time with Scala and Akka.

Some features I really enjoyed:

  • Java Support
    Yeah, I’d prefer pure Scala, but sometimes it doesn’t make sense to rewrite something when you could just drop it in. Play! has no problems with some or all of your source files being .java.
  • The module system rocks
    Modules are basically Play! apps, added as an overlay which can extend any or all parts of a an app. The library of existing modules contains some great stuff too.
  • Creating custom view tags is quite easy
    I didn’t start doing this until the end of the project, but I wish I had. Custom tags can save alot of code and time, and are so easy to write there’s no excuse not to.

Maybe most impressive to me though, was that from the first time I decompressed Play! to the first time I could show my boss a working prototype of my project was just a couple days — I think I’d be hard pressed to find a framework with less overhead/learning curve.

P.S. There’s also no Play! book(s)… whatever that says about Play! vs Lift.

Answer:

Check out Play 1.2s new async constructs (in Java):

http://www.playframework.org/documentation/1.2.1/asynchronous

You can do Comet and WebSockets in a snap with a couple of lines of code. Very easy to understand.

In my opinion Play! is much simpler to set up, learn and use. It is less academic and has more practical solutions to common web-based app challenges.

It’s also the opposite of Lift in terms of statefulness. Play! promotes a stateless development and deployment model that makes it much easier to scale the app horizontally.

Answer:

I think it is the opposite – that Play has better performance. Play is using Netty, and not a traditional Java Servlet Container. By that Play is not using the limited architecture with a thread per connection. Play is sometimes compared with Node.js for performance reasons

AFAIK all modern servlet containers don’t use “limited architecture with a thread per connection”. Below is a quote from article on JavaWorld:

Thanks to the non-blocking I/O capability introduced in Java 4′s New I/O APIs for the Java Platform (NIO) package, a persistent HTTP connection doesn’t require that a thread be constantly attached to it. Threads can be allocated to connections only when requests are being processed. When a connection is idle between requests, the thread can be recycled, and the connection is placed in a centralized NIO select set to detect new requests without consuming a separate thread. This model, called thread per request, potentially allows Web servers to handle a growing number of user connections with a fixed number of threads. With the same hardware configuration, Web servers running in this mode scale much better than in the thread-per-connection mode. Today, popular Web servers — including Tomcat, Jetty, GlassFish (Grizzly), WebLogic, and WebSphere — all use thread per request through Java NIO. For application developers, the good news is that Web servers implement non-blocking I/O in a hidden manner, with no exposure whatsoever to applications through servlet APIs.

Regardind Lift, IMHO it has excellent performance (and is easy-to-use) especially when you deal with Comet requests.