Showing posts with label LiftFilter. Show all posts
Showing posts with label LiftFilter. Show all posts

Tuesday, 16 October 2012

Getting started with liftweb framework


Required 
Java
maven2 or sbt
jetty - a Java servlet engine
scala

STEP 1 Install Java and configure PATH
http://www.oracle.com/technetwork/java/javase/downloads/jdk7u9-downloads-1859576.html

STEP 2 Install scala 2.9.2
Download scala from http://www.scala-lang.org/downloads

$ wget  http://www.scala-lang.org/files/archive/scala-2.9.2.tgz

$ sudo mkdir /opt/scala292
Open the dowloaded file (Archive manager - file-roller) and extract to /opt/scala/

Create a sybolic link (future proof the install):
$ ln -s /opt/scala/scala-2.9.2 /opt/scala292/current

Define environment variable SCALA_HOME by editing /etc/profile and adding the line:
export SCALA_HOME=/opt/scala292/current

Add the Scala executables to your path by editing /etc/profile and adding the line:
export PATH=$PATH:$SCALA_HOME/bin

restart computer, and enter command
scala -version
Scala code runner version 2.9.2  -- Copyright 2002-2011, LAMP/EPFL


STEP 3 Install maven
$ sudo apt-get install maven2

OR
Download maven from http://maven.apache.org/download.html and configure PATH.
(mine /etc/profile is)

JAVA_HOME=/usr/java/jdk1.7.0; export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH; export PATH
export PATH=$PATH:/home/prayag/apache-maven-3.0.4/bin


STEP 4 Install jetty, an HTTP server, HTTP client, and javax.servlet container
$ sudo apt-get install jetty


STEP 5 Create liftweb app with mvn
$ mkdir /home/prayag/workspace_lift
$ cd /home/prayag/workspace_lift

Issue the following maven2 command for a lift project template downloaded from http://scala-tools.org/repo-snapshots :

mvn archetype:generate \
 -DarchetypeGroupId=net.liftweb \
 -DarchetypeArtifactId=lift-archetype-basic_2.9.1 \
 -DarchetypeVersion=2.4-M5 \
 -DarchetypeRepository=http://scala-tools.org/repo-releases \
 -DremoteRepositories=http://scala-tools.org/repo-releases \
 -DgroupId=com.zam.gwitter \
 -DartifactId=gwitter \
 -Dversion=1.0

The architecture of app will be as follows :

5 - A) The dependencies in pom.xml will be as follows :
<repositories>
    <repository>
      <id>scala-tools.releases</id>
      <name>Scala-Tools Dependencies Repository for Releases</name>
      <url>http://scala-tools.org/repo-releases</url>
    </repository>
    <repository>
      <id>java.net.maven2</id>
      <name>java.net Maven2 Repository</name>
      <url>http://download.java.net/maven/2/</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>scala-tools.releases</id>
      <name>Scala-Tools Plugins Repository for Releases</name>
      <url>http://scala-tools.org/repo-releases</url>
    </pluginRepository>
  </pluginRepositories>

  <dependencies>
    <dependency>
      <groupId>net.liftweb</groupId>
      <artifactId>lift-mapper_2.9.1</artifactId>
      <version>2.4-M5</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>0.9.26</version>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.2.138</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.scala-tools.testing</groupId>
      <artifactId>specs_2.9.1</artifactId>
      <version>1.6.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty</artifactId>
      <version>6.1.25</version>
      <scope>test</scope>
    </dependency>
    <!-- for LiftConsole -->
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-compiler</artifactId>
      <version>${scala.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

5 - B) The gwitter/src/main/webapp/WEB-INF/web.xml file will be as follows :
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<filter>
  <filter-name>LiftFilter</filter-name>
  <display-name>Lift Filter</display-name>
  <description>The Filter that intercepts lift calls</description>
  <filter-class>net.liftweb.http.LiftFilter</filter-class>
</filter>
   

<filter-mapping>
  <filter-name>LiftFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>


5 - C) The gwitter/src/main/webapp/index.html will be as follows :
<div class="lift:surround?with=default;at=content">
  <h2>Welcome to your project!</h2>
  <p>
    <div class="lift:helloWorld.howdy">
      Welcome to gwitter at <span id="time">The current time</span>
    </div>
  </p>
</div>



5 - D) The com/zam/gwitter/model/User.scala will be as follows :
package com.zam.gwitter {
package model {

import _root_.net.liftweb.mapper._
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._

/**
 * The singleton that has methods for accessing the database
 */
object User extends User with MetaMegaProtoUser[User] {
  override def dbTableName = "User" // define the DB table name
  override def screenWrap = Full(<lift:surround with="default" at="content">
          <lift:bind /></lift:surround>)
  // define the order fields will appear in forms and output
  override def fieldOrder = List(id, firstName, lastName, email,
  locale, timezone, password, textArea)

  // comment this line out to require email validations
  override def skipEmailValidation = true
}

/**
 * An O-R mapped "User" class that includes first name, last name, password and we add a "Personal Essay" to it
 */
class User extends MegaProtoUser[User] {
  def getSingleton = User // what's the "meta" server

  // define an additional field for a personal essay
  object textArea extends MappedTextarea(this, 2048) {
    override def textareaRows  = 10
    override def textareaCols = 50
    override def displayName = "Personal Essay"
  }
}
}
}

5 - E)  The com/zam/gwitter/snippet/HelloWorld.scala snippet will be as follows:
package com.zam.gwitter {
package snippet {

import _root_.scala.xml.{NodeSeq, Text}
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._
import _root_.java.util.Date
import com.zam.gwitter.lib._
import Helpers._

class HelloWorld {
  lazy val date: Box[Date] = DependencyFactory.inject[Date] // inject the date

  // bind the date into the element with id "time"
  def howdy = "#time *" #> date.map(_.toString)

  /*
   lazy val date: Date = DependencyFactory.time.vend // create the date via factory

   def howdy = "#time *" #> date.toString
   */
}//end of class
}
}

5 - F)  The com/zam/gwitter/lib/DependencyFactory.scala will be as follows :
package com.zam.gwitter {
package lib {

import net.liftweb._
import http._
import util._
import common._
import _root_.java.util.Date

/**
 * A factory for generating new instances of Date.  You can create
 * factories for each kind of thing you want to vend in your application.
 * An example is a payment gateway.  You can change the default implementation,
 * or override the default implementation on a session, request or current call
 * stack basis.
 */
object DependencyFactory extends Factory {
  implicit object time extends FactoryMaker(Helpers.now _)

  /**
   * objects in Scala are lazily created.  The init()
   * method creates a List of all the objects.  This
   * results in all the objects getting initialized and
   * registering their types with the dependency injector
   */
  private def init() {
    List(time)
  }
  init()
}

/*
/**
 * Examples of changing the implementation
 */
sealed abstract class Changer {
  def changeDefaultImplementation() {
    DependencyFactory.time.default.set(() => new Date())
  }

  def changeSessionImplementation() {
    DependencyFactory.time.session.set(() => new Date())
  }

  def changeRequestImplementation() {
    DependencyFactory.time.request.set(() => new Date())
  }

  def changeJustForCall(d: Date) {
    DependencyFactory.time.doWith(d) {
      // perform some calculations here
    }
  }
}
*/
}
}


STEP 6 Run a liftweb app
Issue mvn jetty:run and access the web application in your browser via http://localhost:8080

STEP 7 RESULT





REFERENCES
1 - Lift + Scala, Installation + First contact, 11. AUGUST 2010 available at http://tuxpool.blogspot.com/2010/08/lifting-scala-installation-first.html

2 - Using Maven, available at https://www.assembla.com/wiki/show/liftweb/Using_Maven