From b49f5399d3fbed93032d4e01cfd1b748ed5a59cf Mon Sep 17 00:00:00 2001 From: David Pollak Date: Tue, 19 Feb 2013 12:38:33 -0800 Subject: [PATCH] Simply Lift --- docs/simply_lift.md | 547 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100644 docs/simply_lift.md diff --git a/docs/simply_lift.md b/docs/simply_lift.md new file mode 100644 index 0000000000..844a3f9488 --- /dev/null +++ b/docs/simply_lift.md @@ -0,0 +1,547 @@ +# Simply Lift + +> David Pollak +> February 19, 2013 +>
+> Copyright © 2010-2013 by David Pollak +> Creative Commons License +>
+> Simply Lift by http://simply.liftweb.net is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Based on a work at https://github.com/lift/framework. + + +## The Lift Web Framework + +### Introduction + +The Lift Web Framework provides web application developers tools to make writing security, interacting, scalable web applications easier than with any other web framework. After reading Part I of this book, you should understand Lift's core concepts and be able to write Lift applications. But with anything, practice is important. I have been writing Lift and Scala for 6 years, and even I learn new things about the language and the framework on a weekly basis. Please consider Lift an path and an exploration, rather than an end point. + +“Yo, David, stop yer yappin'. I'm coming from Rails|Spring|Struts|Django and I want to get started super fast with Lift.” See From MVC. + +Lift is built on top of the [Scala](http://scala-lang.org) programming language. Scala runs on the [Java Virtual Machine](http://www.oracle.com/technetwork/java/index.html). Lift applications are typically packaged as [http://en.wikipedia.org/wiki/WAR_(Sun_file_format)||WAR] files and run as a [http://www.oracle.com/technetwork/java/index-jsp-135475.html||J/EE Servlets] or Servlet Filters. This book will provide you with the core concepts you need to successfully write Lift web applications. The book assumes knowledge of Servlets and Servlet containers, the Scala Language (Chapters 1-6 of [http://apress.com/book/view/9781430219897||Beginning Scala] gives you a good grounding in the language), build tools, program editors, web development including HTML and JavaScript, etc. Further, this book will not explore persistence. Lift has additional modules for persisting to relational and non-relational data stores. Lift doesn't distinguish as to how an object is materialized into the address space... Lift can treat any object any old way you want. There are many resources (including [http://exploring.liftweb.net/||Exploring Lift]) that cover ways to persist data from a JVM. + +Lift is different from most web frameworks and it's likely that Lift's differences will present a challenge and a friction if you are familiar with the MVCMVC school of web frameworksThis includes Ruby on Rails, Struts, Java Server Faces, Django, TurboGears, etc.. But Lift is different and Lift's differences give you more power to create interactive applications. Lift's differences lead to more concise web applications. Lift's differences result in more secure and scalable applications. Lift's differences let you be more productive and make maintaining applications easier for the future you or whoever is writing your applications. Please relax and work to understand Lift's differences... and see how you can make best use of Lift's features to build your web applications. + +Lift creates abstractions that allow easier expression of business logic and then maps those abstractions to HTTP and HTML. This approach differs from traditional web frameworks which build abstractions on top of HTTP and HTML and require the developer to bridge between common business logic patterns and the underlying protocol. The difference means that you spend more time thinking about your application and less time thinking about the plumbing. + +I am a “concept learner.” I learn concepts and then apply them over and over again as situations come up. This book focuses a lot on the concepts. If you're a concept learner and like my stream on conciousness style, this book will likely suit you well. On the other hand, it may not. + +Up to date versions of this book are available in PDF form at http://simply.liftweb.net/Simply_Lift.pdf. The source code for this book is available at [https://github.com/dpp/simply_lift||https://github.com/dpp/simply_lift]. + +If you've got questions, feedback, or improvements to this document, please join the conversation on the [http://groups.google.com/group/liftweb||Lift Google Group]. + +I'm a “roll up your sleaves and get your hands dirty with code” kinda guy... so let's build a simple Chat application in Lift. This application will allow us to demonstrate some of Lift's core features as well as giving a “smack in the face” demonstration of how Lift is different. + +### The ubiquitous Chat app + +Writing a multi-user chat application in Lift is super-simple and illustrates many of Lift's core concepts. + +The Source Code can be found at [https://github.com/dpp/simply_lift/tree/master/chat]. + +#### The View + +When writing a Lift app, it's often best to start off with the user interface... build what the user will see and then add behavior to the HTML page. So, let's look at the Lift template that will make up our chat application. + + + +It's a valid HTML page, but there are some hinky looking class attributes. The first one is . The class in this case says “the actual page content is contained by the element with id='main'.” This allows you to have valid HTML pages for each of your templates, but dynamically add “chrome” around the content based on one or more chrome templates. + +Let's look at the
. It's got a funky class as well: lift:surround?with=default;at=content. This class invokes a snippet which surrounds the
with the default template and inserts the
and its children at the element with id “content” in the default template. Or, it wraps the default chrome around the
. For more on snippets, see [sec:Snippets]. + +Next, we define how we associate dynamic behavior with the list of chat elements:
. The “comet” snippet looks for a class named Chat that extends CometActor and enables the mechanics of pushing content from the CometActor to the browser when the state of the CometActor changes. + +#### The Chat Comet component + +The [http://en.wikipedia.org/wiki/Actor_model||Actor Model] provides state in functional languages include Erlang. Lift has an Actor library and LiftActors (see [sec:LiftActor]) provides a powerful state and concurrency model. This may all seem abstract, so let's look at the Chat class. + + + +The Chat component has private state, registers with the ChatServer, handles incoming messages and can render itself. Let's look at each of those pieces. + +The private state, like any private state in prototypical object oriented code, is the state that defines the object's behavior. + +registerWith is a method that defines what component to register the Chat component with. Registration is a part of the Listener (or [http://en.wikipedia.org/wiki/Observer_pattern||Observer]) pattern. We'll look at the definition of the ChatServer in a minute. + +The lowPriority method defines how to process incoming messages. In this case, we're Pattern Matching (see [sec:Pattern-Matching]) the incoming message and if it's a Vector[String], then we perform the action of setting our local state to the Vector and re-rendering the component. The re-rendering will force the changes out to any browser that is displaying the component. + +We define how to render the component by defining the CSS to match and the replacement (See [sec:CSS-Selector-Transforms]). We match all the
  • tags of the template and for each message, create an
  • tag with the child nodes set to the message. Additionally, we clear all the elements that have the clearable in the class attribute. + +That's it for the Chat CometActor component. + +#### The ChatServer + +The ChatServer code is: + + + +The ChatServer is defined as an object rather than a class. This makes it a singleton which can be referenced by the name ChatServer anywhere in the application. Scala's singletons differ from Java's static in that the singleton is an instance of an object and that instance can be passed around like any other instance. This is why we can return the ChatServer instance from the registerWith method in that Chat component. + +The ChatServer has private state, a Vector[String] representing the list of chat messages. Note that Scala's type inferencer infers the type of msgs so you do not have to explicitly define it. + +The createUpdate method generates an update to send to listeners. This update is sent when a listener registers with the ChatServer or when the updateListeners() method is invoked. + +Finally, the lowPriority method defines the messages that this component can handle. If the ChatServer receives a String as a message, it appends the String to the Vector of messages and updates listeners. + +#### User Input + +Let's go back to the view and see how the behavior is defined for adding lines to the chat. + +
    defines an input form and the form.ajax snippet turns a form into an Ajax (see [sec:Ajax]) form that will be submitted back to the server without causing a full page load. + +Next, we define the input form element: . It's a plain old input form, but we've told Lift to modify the 's behavior by calling the ChatIn snippet. + +#### Chat In + +The ChatIn snippet (See [sec:Snippets]) is defined as: + + + +The code is very simple. The snippet is defined as a method that associates a function with form element submission, onSubmit. When the element is submitted, be that normal form submission, Ajax, or whatever, the function is applied to the value of the form. In English, when the user submits the form, the function is called with the user's input. + +The function sends the input as a message to the ChatServer and returns JavaScript that sets the value of the input box to a blank string. + +#### Running it + +Running the application is easy. Make sure you've got Java 1.6 or better installed on your machine. Change directories into the chat directory and type sbt update ~jetty-run. The Simple Build Tool will download all necessary dependencies, compile the program and run it. + +You can point a couple of browsers to http://localhost:8080 and start chatting. + +Oh, and for fun, try entering