Newbie question

10 views
Skip to first unread message

Donald McLean

unread,
Jun 18, 2010, 3:26:08 PM6/18/10
to liftweb
We are doing a technology evaluation where Lift is competing against
GWT and RichFaces/JSF. We are implementing a small piece of real
functionality in each technology and then we will prepare a
recommendation for management. So far we have completed the GWT
implementation (full pass) and the RichFaces/JSF implementation (full
pass, with reservations). Now I'm starting on the Lift implementation.

We want an interactive web application that consists of a single page
divided up into multiple panels. Based on user actions and status
changes contents of the individual panels may get updated and/or whole
panels would be replaced by other panels.

Changing out whole panels was straightforward in GWT and only slightly
more complicated in RichFaces/JSF. It isn't quite clear to me how to
do something like this in Lift. Skimming through the Lift book, I can
see pieces that look like they could be used for something like this
but it's very fuzzy as to how they would fit together. I would greatly
appreciate an outline for how something like this would work.

Also, why is it so hard to navigate the ScalaDoc? Having things broken
up into small sections isn't very helpful when looking for a specific
class (I never did find NodeSeq).

Any help is greatly appreciated.

Donald

David Pollak

unread,
Jun 18, 2010, 5:05:19 PM6/18/10
to lif...@googlegroups.com
Howdy,

I put together a simple example of a Lift app that does what you've asked.  You can see it at http://github.com/dpp/FlipSwitch

This is a place where Lift actually really shines.  Because Lift is view-first, your page is composed of independent elements and you can insert, replace, re-arrange, etc. elements to your heart's content.  Further, because Scala's functions close over scope, you have a very, very easy way to capture the current scope for the behavior of an Ajax widget.  Also note that the Ajax select element is resistant to parameter tampering... you can be sure that the value passed back to your application as a result of the user selecting an item is one of the legal items in the Ajax select.

Here's the core code for those that don't want to click through:

object Quad {
  // the legal values and state for each of the quadrants
  val upperLeft = List("a", "b", "c")
  object upperLeftValue extends SessionVar(upperLeft.head) // default to "a"

  val upperRight = List("b", "z", "q")
  object upperRightValue extends SessionVar(upperRight.head)

  val lowerLeft = List("c", "n", "a")
  object lowerLeftValue extends SessionVar(lowerLeft.head)
  
  val quads = Map("UL" -> (upperLeft -> upperLeftValue),
                  "UR" -> (upperRight -> upperRightValue),
                  "LL" -> (lowerLeft -> lowerLeftValue))
  
  // define the transformation of the incoming XHTML
  // to the outgoing XHTML. In this case, we're
  // going to substitute snippet's rather than transforming
  // the input to the output. For an example of transformation,
  // see Chat.scala
  def render(in: NodeSeq): NodeSeq = {
    val myQuad =
      S.attr("for"). // get the "for" attribute
    map(_.toUpperCase.trim). // convert it to upper case
    filter(quads.contains _). // make sure it's valid
    openOr("UL") // if it's not valid, assume the upper left

    // take a snapshot of the valid set of options
    // and the holder of the current selection
    val (set, current) = quads(myQuad)

    // render the output... the thing to put into
    // the quadrant. It's a snippet that will
    // then be expanded into a new template
    // plus an ajax selector for changing the
    // template the quadrant displays
    def renderOutput(): NodeSeq =
      <lift:embed what={"/template-"+current}/> ++
    SHtml.ajaxSelectObj(set.map(s => s -> s), // this is necessary because
                                              // this parameter is actually
                                              // the name and the value, but
                                              // in this case they're the same
                     Full(current.is), // the current value
                     updateSpan _) // what to do when the select is changed

    // update the span
    def updateSpan(value: String): JsCmd = {
      current.set(value) // set the current value. Note that the value
                         // of current is the scope in which this method
                         // was created, so it captures the correct
                         // reference for current

      SetHtml(myQuad, renderOutput()) // set the span to the newly calculated
                                       // output
    }


    renderOutput()
  }
}


So, this example (including the Comet chat component that lives in one of the quadrants), is < 200 lines of code.  How many lines of code were the other prototypes you built?

Thanks,

David


--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.




--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Blog: http://goodstuff.im
Surf the harmonics

Derek Chen-Becker

unread,
Jun 18, 2010, 6:53:06 PM6/18/10
to lif...@googlegroups.com
Simply awesome. I was going to talk about the AJAX and Comet support, but you've provided something much more effective here :)

Donald McLean

unread,
Jun 18, 2010, 8:27:15 PM6/18/10
to lif...@googlegroups.com
Well, the other prototypes were actual implementations of a basic
piece of the functionality for our real application. When I finish the
Lift version, then we'll see how it stacks up.

GWT is pretty slick, I have to say.

Thank you,

Donald

Donald McLean

unread,
Jun 23, 2010, 11:33:11 AM6/23/10
to lif...@googlegroups.com
On Fri, Jun 18, 2010 at 5:05 PM, David Pollak
<feeder.of...@gmail.com> wrote:
>
> I put together a simple example of a Lift app that does what you've asked.
> You can see it at http://github.com/dpp/FlipSwitch

Thank you, David for the example. Unfortunately, I can't get it to
work in my environment. I'm getting an exception and I have no idea
what the cause is or how to solve it:

23 Jun 2010 11:28:36,196 - ERROR
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/liftdemo].[default]
- Servlet.service() for
servlet default threw exception
java.lang.NullPointerException
at net.liftweb.http.provider.HTTPProvider$$anonfun$service$3.apply(HTTPProvider.scala:61)
at net.liftweb.http.provider.HTTPProvider$$anonfun$service$3.apply(HTTPProvider.scala:61)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.URLRewriter$.doWith(Req.scala:618)
at net.liftweb.http.provider.HTTPProvider$class.service(HTTPProvider.scala:60)
at net.liftweb.http.LiftFilter.service(LiftServlet.scala:586)
at net.liftweb.http.provider.servlet.ServletFilterProvider$class.protected$service(ServletFilterProvider.scala:67)
at net.liftweb.http.LiftFilter.protected$service(LiftServlet.scala:586)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1$$anonfun$apply$1.apply(ServletFilterProvider.scala:67)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1$$anonfun$apply$1.apply(ServletFilterProvider.scala:62)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10$$anonfun$apply$11$$anonfun$apply$12.apply(Vars.scala:335
)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10$$anonfun$apply$11.apply(Vars.scala:334)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10.apply(Vars.scala:333)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9.apply(Vars.scala:332)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$class.apply(Vars.scala:331)
at net.liftweb.http.RequestVarHandler$.apply(Vars.scala:250)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1.apply(ServletFilterProvider.scala:61)
at net.liftweb.http.provider.servlet.ServletFilterProvider$$anonfun$doFilter$1.apply(ServletFilterProvider.scala:61)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10$$anonfun$apply$11$$anonfun$apply$12.apply(Vars.scala:335
)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10$$anonfun$apply$11.apply(Vars.scala:334)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9$$anonfun$apply$10.apply(Vars.scala:333)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$$anonfun$apply$9.apply(Vars.scala:332)
at net.liftweb.util.ThreadGlobal.doWith(ThreadGlobal.scala:71)
at net.liftweb.http.CoreRequestVarHandler$class.apply(Vars.scala:331)
at net.liftweb.http.TransientRequestVarHandler$.apply(Vars.scala:254)
at net.liftweb.http.provider.servlet.ServletFilterProvider$class.doFilter(ServletFilterProvider.scala:60)
at net.liftweb.http.LiftFilter.doFilter(LiftServlet.scala:586)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:619)

David Pollak

unread,
Jun 23, 2010, 12:28:24 PM6/23/10
to lif...@googlegroups.com
This issue has come up previously when running with Tomcat: http://groups.google.com/group/liftweb/browse_thread/thread/211981131bc7d192/d7c860ccadb32dd1?#d7c860ccadb32dd1

I thought that we had fixed the issue.  I'm heading off on vacation in 30 minutes.

Marius -- please reproduce this issue on whatever version of Tomcat that's causing the issue (Donald... what's the version of Tomcat and OS you're using) and get a fix (if the problem is a bug in Tomcat, we can emit a message stating that version xxx of Tomcat has the following bug [url], please upgrade to a version yyy) so we can spin an RC3.  This in my opinion is a show-stopper.


--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.

Donald McLean

unread,
Jun 23, 2010, 12:41:33 PM6/23/10
to lif...@googlegroups.com
On Wed, Jun 23, 2010 at 12:28 PM, David Pollak
<feeder.of...@gmail.com> wrote:
> This issue has come up previously when running with Tomcat:
> http://groups.google.com/group/liftweb/browse_thread/thread/211981131bc7d192/d7c860ccadb32dd1?#d7c860ccadb32dd1
>
> I thought that we had fixed the issue.  I'm heading off on vacation in 30
> minutes.
>
> Marius -- please reproduce this issue on whatever version of Tomcat that's
> causing the issue (Donald... what's the version of Tomcat and OS you're
> using) and get a fix (if the problem is a bug in Tomcat, we can emit a
> message stating that version xxx of Tomcat has the following bug [url],
> please upgrade to a version yyy) so we can spin an RC3.  This in my opinion
> is a show-stopper.

I have contacted my IT folks to see if I can get Tomcat 6.0.26 installed.

According to the Tomcat manager app:

Tomcat version: Apache Tomcat/6.0.20
JVM version: 1.6.0_15-b03
JVM vendor: Sun Microsystems Inc.
OS: Linux
OS version: 2.6.18-53.1.14.el5
OS architecture: amd64

Marius

unread,
Jun 23, 2010, 1:40:15 PM6/23/10
to Lift
Historically this problem occurred when an exception has been thrown
from Boot. Last time Tim run into this issue and the problem was that
an exception was thrown due to JDBC settings. Please see this thread:

http://groups.google.com/group/liftweb/browse_thread/thread/6886f975ed981c52/470bdf8401c1be6b?lnk=gst&q=NullPointerException#470bdf8401c1be6b

To be sure please wrap your boot code into a try{.... }catch {e =>
e.printStackTrace()} and let us know what you see.

I'm opening now a ticket and fix it however I'm not sure if it'll make
it into 2.0.

Br's,
Marius

On Jun 23, 7:41 pm, Donald McLean <dmclea...@gmail.com> wrote:
> On Wed, Jun 23, 2010 at 12:28 PM, David Pollak
>
> <feeder.of.the.be...@gmail.com> wrote:
> > This issue has come up previously when running with Tomcat:
> >http://groups.google.com/group/liftweb/browse_thread/thread/211981131...

Donald McLean

unread,
Jun 23, 2010, 2:22:42 PM6/23/10
to lif...@googlegroups.com
On Wed, Jun 23, 2010 at 1:40 PM, Marius <marius...@gmail.com> wrote:
> Historically this problem occurred when an exception has been thrown
> from Boot. Last time Tim run into this issue and the problem was that
> an exception was thrown due to JDBC settings. Please see this thread:
>
> http://groups.google.com/group/liftweb/browse_thread/thread/6886f975ed981c52/470bdf8401c1be6b?lnk=gst&q=NullPointerException#470bdf8401c1be6b
>
> To be sure please wrap your boot code into a try{.... }catch {e =>
> e.printStackTrace()} and let us know what you see.

Bingo!

There was a problem with my build - lift-json.jar was missing and I
got a ClassNotFound exception. All working now.

Thank you.

Donald

Marius

unread,
Jun 23, 2010, 3:58:34 PM6/23/10
to Lift
Cool ! ... I hope you'll be choosing Lift :). I may be biased as I'm
part of it, but I find it far more superior than GWT. But never mind
me, convince yourself if you like it or not. JSF&co? ... yack !

On Jun 23, 9:22 pm, Donald McLean <dmclea...@gmail.com> wrote:
> On Wed, Jun 23, 2010 at 1:40 PM, Marius <marius.dan...@gmail.com> wrote:
> > Historically this problem occurred when an exception has been thrown
> > from Boot. Last time Tim run into this issue and the problem was that
> > an exception was thrown due to JDBC settings. Please see this thread:
>
> >http://groups.google.com/group/liftweb/browse_thread/thread/6886f975e...
Reply all
Reply to author
Forward
0 new messages