FAQ

From LiftWiki

Jump to: navigation, search

Contents

How to retrieve the current logged in user?

There are three kinds of Cans: Full cans, Empty cans, and Failure cans (which are essentially just Empty cans with some attached info about why the operation failed).

The "map" and "openOr" methods are defined on all Cans, but have different behavior depending on the type of Can that they are applied to. When "map" is called on a Full can, it will apply the given function to the contents of the Can, returning a Can with the result. When "map" is applied on an Empty can, it returns the Empty can. When "openOr" is called on a Full can, it returns the contents of the Can. When "openOr" is called on an Empty can, it returns the argument to "openOr".

So let's look at David's code:

 User.currentUser.map(_.lastName).openOr("Not Logged In")

First, let's desugar the syntax. The "_.lastName" is Scala shorthand for defining a function. In this case, it's shorthand for something like:

 (u: User) => u.lastName

That is to say, it's a function that takes a User and returns a String of the user's last name.

So: User.currentUser returns a Can. The Can is Full (and contains the current logged in user) if there is a current logged in user. The Can is Empty if no user is logged in.

Then map(_.lastName) will return a Full can (with a string containing the current logged in user's last name) if there is a current logged in user. It will return an Empty can if no user is logged in.

Finally, openOr("You are not logged in") will return the contents of the Can if the Can is Full (in this case, the content is the current logged in user's last name), or "You are not logged in" if the Can is Empty.

The Can is just a more advanced version of Scala's Option class. You might want to read David's blog post about how lift used to use the Option class. (Now lift uses Can, but the concepts are the same. Just mentally replace "Some" with "Full", "None" with "Empty", and "getOrElse" with "openOr".)

Jorge Eugenio Ortiz Hinojosa - 2007-11-21 - lift 0.3.0 (extract from discussions "how to retreive...")

toForm field Order

The order fields appear when toForm is called on a model object is by default alphabetical.
If you don't want this then add override def fieldOrder = field1 :: field2 :: ... :: Nil with the desired order.

Is it possible to start adding new functionality (new pages, new modules) with lift, into existing servlet java application ? Will the session be shared ?

lift is implemented as a Filter. It only handles Servlet requests that it's "supposed" to.

"supposed" is defined in LiftServlet.isLiftRequest_? (it's a partial function. If it's defined, it returns true or false).

If lift doesn't handle the request, it's passed on in the Filter chain (thanks to Viktor for recommending this strategy.)

lift interoperates with everything else in the servlet container.

So, all you'd have to do is define the isLiftRequest_? partial function to tell lift to deal with certain URLs and your existing Servlet would deal with the rest and both lift and your other servlet would share the same Servlet Context.

Long way of saying "yes".

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Add lift to existing servlet web application")

Could the Boot class get given a reference of the LiftServlet instead of referring to it as a Singleton?

No. And why? Lots of stuff in lift references LiftServlet. It's a Singleton. If we have to have a stupid-ass factory paradigm that's implemented a different way for vended Singleton, then we're back to Java hell. We're at the meta-meta-factory-factory blah blah blah stuff. Sorry for coming down on this question, but in many cases, Java stuff is over-thought out for no understandable reason. For example, how many times do you substitute the XML parser in Java?

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

What is the lifecycle of a snippet?

...Specifically around forms. In the hellodarwin example, we're led astray at first before being introduced to the "RequestVar" type, the explanation for why this is needed and what it does confused me somewhat.

It depends on whether the snippet is a StatefulSnippet or not.

If it's not stateful, then a new instance of the snippet is created each time the snippet is referenced during a render cycle.

However, functions that appear in the snippet may be bound to instance or local variables in the snippet and those variables (and the instance of the snippet that they're bound to) may have a life beyond the current page rendering.

Sound confusing? Spend a little time familiarizing yourself with the subtleties of how anonymous Scala functions are bound to variable scope and then I think the answer may be more obvious.

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

Why AMQP instead of JMS?

Because AMQP is a wire standard rather than an API standard and I believe the folks at LShift/Cohesive have a drop dead, kick ass solution to messaging in RabbitMQ.

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

Why is the "S" class called "S"?

S is short for Stateful or State. All the Stateful stuff that happens in a request goes through S. I wanted a short name because it was used a lot, so I chose S.

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

How do I add attributes to form fields created with SHtml methods?

Instead of using UnprefixedAttribute to add attributes to elements created using SHtml methods (or any other elements), you can use the following shorthand:

SHtml.text(user.name, user.name = _) % ("size" -> "24") % ("maxlength" -> "48") % ("class" -> "names")

SHtml.textarea(post.comments, post.comments = _) % ("rows" -> "8") % ("cols" -> "50")

Singletons are scattered liberally ...

... around which would make me nervous in a Java context because of coupling and difficulty in testing (e.g. use of LiftServlet in Boot or Users.findAll(...) etc.). What am I missing?

For the model related stuff, you need a Singleton to access the appropriate methods for doing queries. If you did it with something like "QueryManagerFactory.getQueryManager("user").findAll() it would not be type safe.

Before you start jumping up and down yelling dependency injection, consider that most of the actual dependencies are managed with functions and partial functions. These are type safe. Stuff like LiftServlet is a repository for functions, so in many ways, LiftServlet is a factory, not a Singleton. For more, see http://onestepback.org/articles/depinj/index.html

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

object as attribute

This pattern is used a lot:
class SomeClass {
    object someProperty extends SomeObject;
}

and I have no idea why... (I suspect it's my lack of Scala knowledge)

objects are Singletons. This is kind of like saying:

class SomeClass {
   val someProperty = new SomeObject
}

However, there are subtle reasons (mainly having to do with reflection, but also having to do with class naming) why the object syntax is preferred. For the reason that values are carried around in heavier weight objects, see: http://blog.lostlake.org/index.php?/archives/19-Keeping-the-meaning-with-the-bytes.html

David Pollak - 2007-12-11 - lift 0.3.0 (extract from "Some questions from a Java developer")

lift serves Content-Type as application/xhml+xml but I just want text/html

lift serves application/xhtml+xml to browsers that use the Accept header to signify that they understand it. If you would rather always serve your content as text/html, then add the following to your Boot.boot() method

LiftServlet.useXhtmlMimeType = false


Friendly Names for columns/attributes of your Model objects

I missed this for a long time, so I thought I'd point it out.
Below is a snip of a model object. "notes" is the attribute that will appear if you use toForm/asHtml unless you override displayName.
toForm/asHtml will instead display "Comments"

  // the notes of the entry
  object notes extends MappedTextarea(this, 4096) {
    override def displayName = "Comments"
    override def textareaRows  = 10
    override def textareaCols = 50
  }


Snippet Parameter Access

The snippet receives a copy of the child of the snippet. It can also access the attributes of the tag that invoked it:

<lift:foo_bar.show dog="cat" moose="fred">
  <b>This is my message</b>
</lift:foo_bar.show>
class FooBar {
  def show(stuff: Node): NodeSeq = stuff ++ S.attr("dog").map(a => Text("Dog is "+a)).openOr(Text("No dog attr"))
}

What's the "View" folder for?

Marius asks:

Forgive me for asking but what exactly is the role of the view folder when generating a lift project? The lift example application contains a class XMLFun that defines a render function. Is this invoked by lift automatically? Can you please elaborate?


dpp responds:

You can have static templates that live on disk. Useful if you've got designers in your process. You can also have Scala code that renders your templates. Useful for ERB/JSP style coding. Put those templates in your "view" package.
Calls to the templates will be made based on convention:
/foo/bar
will look for the view.Foo class and dispatch to bar. If your view extends InsecureLiftView, /lift/ will look for the bar method and invoke it. This is part of the dangers of taking stuff off the wire... you're exposing all the methods in your class to invocation. If your view extends LiftView, you have to implement the dispatch_& method (or value) which returns a partial function that pattern matches on a string and returns the function that will return your rendered page.

An example of this is in the example site included in the lift repository:
<lift checkout>/liftweb/sites/example/src/main/scala/net/liftweb/example/view/XmlFun.scala

XML parsing error when using lift:comet markup tags?

If you're doing Comet with lift and see XML parsing errors when using lift's comet tags, don't forget to define lift's XML namespace in your templates. For example...

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://liftweb.net">

The error that you would see, if you don't, might look like...

XML Parsing Error: prefix not bound to a namespace
Location: http://localhost:8888/
<span id="LCQBTQA1OTKBTPZ1K5GL2L_outer"><span lift:when="1202157690355" id="LCQBTQA1OTKBTPZ1K5GL2L">
----------------------------------------^

Via: http://groups.google.com/group/liftweb/browse_frm/thread/b4aad50b6c75ee40

Rendering HTML fragments without escaping

I have the description portion of an RSS feed stored in a DB and when I kick it to the screen, it's encoded such that <p> becomes &lt;p&gt;. I'd like it to get on the screen rendered as html. I'm grabbing the DB record and flatmapping it like in most examples.

  RSS.findAll.map(rss => <li>{Unparsed(rss.description)}</li>)

scala.xml.Unparsed is kinda dangerous for distributing unvalidated code (e.g., it's a nice way for cross site scription stuff to creep in.)

Via: http://groups.google.com/group/liftweb/t/c2d4fd23d727d453


How do I determine which Loc in the SiteMap has been requested by the user?

RequestState.location: Can[Loc]

How do I execute code when my application is unloaded?

You can define methods to be called when Lift is unloaded via the LiftRules object in the Boot class.

For example:


def myUnloader(): Unit = {
  // run when Lift is being unloaded
}

LiftRules.unloadHooks += myUnloader _ 

How do I define multiple menus in SiteMap

When creating Loc items in your SiteMap you can add various attributes (LocStuff) to control the display of a menu item. One of these attributes is the LocGroup object for grouping multiple locations by name.

// define your locations and an optional group for each
val entries = Menu(Loc("MenuName1", List("resourcename1"), "Menu Title 1", LocGroup("groupnameA"))) ::
  Menu(Loc("MenuName2", List("resourcename2"), "Menu Title 2", LocGroup("groupnameA"))) ::
  Menu(Loc("MenuName3", List("resourcename3"), "Menu Title 3", LocGroup("groupnameB"))) ::
  Menu(Loc("MenuName4", List("resourcename4"), "Menu Title 4", LocGroup("groupnameB"))) :: Nil
<!-- then add a Menu.group snippet into any html that need this group of locations -->
<lift:Menu.group group="groupnameA"><li><menu:bind /></li></lift:Menu.group>
Personal tools
search|search