Skip to content

Instantly share code, notes, and snippets.

@aolshevskiy
Created June 19, 2011 09:38
Show Gist options
  • Save aolshevskiy/1034015 to your computer and use it in GitHub Desktop.
Save aolshevskiy/1034015 to your computer and use it in GitHub Desktop.
xsbt-lift-basic
package code
import java.io.File
import junit.framework._
import Assert._
import scala.xml.XML
import net.liftweb.util._
import net.liftweb.common._
object AppTest {
def suite: Test = {
val suite = new TestSuite(classOf[AppTest])
suite
}
def main(args : Array[String]) {
junit.textui.TestRunner.run(suite)
}
}
/**
* Unit test for simple App.
*/
class AppTest extends TestCase("app") {
/**
* Rigourous Tests :-)
*/
def testOK() = assertTrue(true)
// def testKO() = assertTrue(false);
/**
* Tests to make sure the project's XML files are well-formed.
*
* Finds every *.html and *.xml file in src/main/webapp (and its
* subdirectories) and tests to make sure they are well-formed.
*/
def testXml() = {
var failed: List[File] = Nil
def handledXml(file: String) =
file.endsWith(".xml")
def handledXHtml(file: String) =
file.endsWith(".html") || file.endsWith(".htm") || file.endsWith(".xhtml")
def wellFormed(file: File) {
if (file.isDirectory)
for (f <- file.listFiles) wellFormed(f)
if (file.isFile && handledXml(file.getName)) {
try {
XML.loadFile(file)
} catch {
case e: org.xml.sax.SAXParseException => failed = file :: failed
}
}
if (file.isFile && handledXHtml(file.getName)) {
PCDataXmlParser(new java.io.FileInputStream(file.getAbsolutePath)) match {
case Full(_) => // file is ok
case _ => failed = file :: failed
}
}
}
wellFormed(new File("src/main/webapp"))
val numFails = failed.size
if (numFails > 0) {
val fileStr = if (numFails == 1) "file" else "files"
val msg = "Malformed XML in " + numFails + " " + fileStr + ": " + failed.mkString(", ")
println(msg)
fail(msg)
}
}
}
package bootstrap.liftweb
import net.liftweb._
import util._
import Helpers._
import common._
import http._
import sitemap._
import Loc._
import mapper._
import code.model._
/**
* A class that's instantiated early and run. It allows the application
* to modify lift's environment
*/
class Boot {
def boot {
if (!DB.jndiJdbcConnAvailable_?) {
val vendor =
new StandardDBVendor(Props.get("db.driver") openOr "org.h2.Driver",
Props.get("db.url") openOr
"jdbc:h2:lift_proto.db;AUTO_SERVER=TRUE",
Props.get("db.user"), Props.get("db.password"))
LiftRules.unloadHooks.append(vendor.closeAllConnections_! _)
DB.defineConnectionManager(DefaultConnectionIdentifier, vendor)
}
// Use Lift's Mapper ORM to populate the database
// you don't need to use Mapper to use Lift... use
// any ORM you want
Schemifier.schemify(true, Schemifier.infoF _, User)
// where to search snippet
LiftRules.addToPackages("code")
// Build SiteMap
def sitemap = SiteMap(
Menu.i("Home") / "index" >> User.AddUserMenusAfter, // the simple way to declare a menu
// more complex because this menu allows anything in the
// /static path to be visible
Menu(Loc("Static", Link(List("static"), true, "/static/index"),
"Static Content")))
def sitemapMutators = User.sitemapMutator
// set the sitemap. Note if you don't want access control for
// each page, just comment this line out.
LiftRules.setSiteMapFunc(() => sitemapMutators(sitemap))
// Use jQuery 1.4
LiftRules.jsArtifacts = net.liftweb.http.js.jquery.JQuery14Artifacts
//Show the spinny image when an Ajax call starts
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
// Make the spinny image go away when it ends
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
// Force the request to be UTF-8
LiftRules.early.append(_.setCharacterEncoding("UTF-8"))
// What is the function to test if a user is logged in?
LiftRules.loggedInTest = Full(() => User.loggedIn_?)
// Use HTML5 for rendering
LiftRules.htmlProperties.default.set((r: Req) =>
new Html5Properties(r.userAgent))
// Make a transaction span the whole HTTP request
S.addAround(DB.buildLoanWrapper)
}
}
seq(WebPlugin.webSettings :_*)
scalaVersion := "2.8.1"
libraryDependencies ++= Seq(
"net.liftweb" %% "lift-webkit" % "2.3" % "compile",
"net.liftweb" %% "lift-mapper" % "2.3" % "compile",
"org.mortbay.jetty" % "jetty" % "6.1.22" % "jetty,test",
"ch.qos.logback" % "logback-classic" % "0.9.26",
"junit" % "junit" % "4.5" % "test",
"org.scala-tools.testing" %% "specs" % "1.6.6" % "test",
"com.h2database" % "h2" % "1.2.138"
)
unmanagedClasspath in Test <+= (scalaInstance) map { (scala) => Attributed.blank(scala.compilerJar) }
resolvers += "Web plugin repo" at "http://siasia.github.com/maven2"
libraryDependencies <+= sbtVersion("com.github.siasia" %% "xsbt-web-plugin" % _)
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://liftweb.net/">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<title class="lift:Menu.title">App: </title>
<style class="lift:CSS.blueprint"></style>
<style class="lift:CSS.fancyType"></style>
<script id="jquery" src="/classpath/jquery.js" type="text/javascript"></script>
<script id="json" src="/classpath/json.js" type="text/javascript"></script>
<style type="text/css">
<![CDATA[
.edit_error_class {
display: block;
color: red;
}
.sidebar ul {
margin:0;
padding:0;
border-bottom:1px solid #ccc;
}
.sidebar ul li {
margin:0;
padding:0;
list-style:none;
border:1px solid #ccc;
border-bottom:none;
}
.sidebar ul li a {
display:block;
padding:3px;
text-indent:30px;
text-decoration:none;
}
.sidebar ul li span {
display:block;
padding:3px;
text-indent:30px;
text-decoration:none;
}
.sidebar ul li a:hover {
background-color: #eee;
}
]]>
</style>
</head>
<body>
<div class="container">
<div class="column span-12 last" style="text-align: right">
<h1 class="alt">app<img alt="" id="ajax-loader" style="display:none; margin-bottom: 0px; margin-left: 5px" src="/images/ajax-loader.gif" /></h1>
</div>
<hr />
<div class="column span-6 colborder sidebar">
<hr class="space" />
<span class="lift:Menu.builder"></span>
<div class="lift:Msgs?showAll=true"></div>
<hr class="space" />
</div>
<div class="column span-17 last">
<div id="content">The main content will get bound here</div>
</div>
<hr />
<div class="column span-23 last" style="text-align: center">
<h4 class="alt">
<a href="http://www.liftweb.net"><i>Lift</i></a>
is Copyright 2007-2011 WorldWide Conferencing, LLC.
Distributed under an Apache 2.0 License.</h4>
</div>
</div>
</body>
</html>
package code
package lib
import net.liftweb._
import http._
import util._
import common._
import 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
}
}
}
*/
package code
package snippet
import scala.xml.{NodeSeq, Text}
import net.liftweb.util._
import net.liftweb.common._
import java.util.Date
import code.lib._
import Helpers._
class HelloWorld {
lazy val date: Box[Date] = DependencyFactory.inject[Date] // inject the date
// replace the contents of the element with id "time" with the date
def howdy = "#time *" #> date.map(_.toString)
/*
lazy val date: Date = DependencyFactory.time.vend // create the date via factory
def howdy = "#time *" #> date.toString
*/
}
package code
package snippet
import org.specs._
import org.specs.runner.JUnit4
import org.specs.runner.ConsoleRunner
import net.liftweb._
import http._
import net.liftweb.util._
import net.liftweb.common._
import org.specs.matcher._
import org.specs.specification._
import Helpers._
import lib._
class HelloWorldTestSpecsAsTest extends JUnit4(HelloWorldTestSpecs)
object HelloWorldTestSpecsRunner extends ConsoleRunner(HelloWorldTestSpecs)
object HelloWorldTestSpecs extends Specification {
val session = new LiftSession("", randomString(20), Empty)
val stableTime = now
override def executeExpectations(ex: Examples, t: =>Any): Any = {
S.initIfUninitted(session) {
DependencyFactory.time.doWith(stableTime) {
super.executeExpectations(ex, t)
}
}
}
"HelloWorld Snippet" should {
"Put the time in the node" in {
val hello = new HelloWorld
Thread.sleep(1000) // make sure the time changes
val str = hello.howdy(<span>Welcome to your Lift app at <span id="time">Time goes here</span></span>).toString
str.indexOf(stableTime.toString) must be >= 0
str.indexOf("Lift app at") must be >= 0
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
<title>Home</title>
</head>
<body class="lift:content_id=main">
<div id="main" class="lift:surround?with=default;at=content">
<h2>Welcome to your project!</h2>
<p>
<span class="lift:helloWorld.howdy">
Welcome to your Lift app at <span id="time">Time goes here</span>
</span>
</p>
</div>
</body>
</html>
<div id="main" class="lift:surround?with=default;at=content">
Static content... everything you put in the /static
directory will be served without additions to SiteMap
</div>
import bootstrap.liftweb.Boot
import scala.tools.nsc.MainGenericRunner
object LiftConsole {
def main(args : Array[String]) {
// Instantiate your project's Boot file
val b = new Boot()
// Boot your project
b.boot
// Now run the MainGenericRunner to get your repl
MainGenericRunner.main(args)
// After the repl exits, then exit the scala script
exit(0)
}
}
import org.mortbay.jetty.Connector
import org.mortbay.jetty.Server
import org.mortbay.jetty.webapp.WebAppContext
import org.mortbay.jetty.nio._
object RunWebApp extends Application {
val server = new Server
val scc = new SelectChannelConnector
scc.setPort(8080)
server.setConnectors(Array(scc))
val context = new WebAppContext()
context.setServer(server)
context.setContextPath("/")
context.setWar("src/main/webapp")
server.addHandler(context)
try {
println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP")
server.start()
while (System.in.available() == 0) {
Thread.sleep(5000)
}
server.stop()
server.join()
} catch {
case exc : Exception => {
exc.printStackTrace()
System.exit(100)
}
}
}
package code
package model
import net.liftweb.mapper._
import net.liftweb.util._
import net.liftweb.common._
/**
* The singleton that has methods for accessing the database
*/
object User extends User with MetaMegaProtoUser[User] {
override def dbTableName = "users" // 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"
}
}
<?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>
<div>
<wizard:screen_info><div>Page <wizard:screen_number></wizard:screen_number> of <wizard:total_screens></wizard:total_screens></div></wizard:screen_info>
<wizard:wizard_top> <div> <wizard:bind></wizard:bind> </div> </wizard:wizard_top>
<wizard:screen_top> <div> <wizard:bind></wizard:bind> </div> </wizard:screen_top>
<wizard:errors> <div> <ul> <wizard:item> <li> <wizard:bind></wizard:bind> </li> </wizard:item> </ul> </div> </wizard:errors>
<div>
<wizard:fields>
<table>
<tbody>
<tr lift:bind="wizard:line">
<td>
<wizard:label>
<label wizard:for="">
<wizard:bind></wizard:bind>
</label>
</wizard:label>
<wizard:help>
<span>
<wizard:bind></wizard:bind>
</span>
</wizard:help>
<wizard:field_errors>
<ul>
<wizard:error>
<li>
<wizard:bind></wizard:bind>
</li>
</wizard:error>
</ul>
</wizard:field_errors>
</td>
<td>
<wizard:form></wizard:form>
</td>
</tr>
</tbody>
</table>
</wizard:fields>
</div>
<div>
<table>
<tr>
<td>
<wizard:prev></wizard:prev>
</td>
<td>
<wizard:cancel></wizard:cancel>
</td>
<td>
<wizard:next></wizard:next>
</td>
</tr>
</table>
</div>
<wizard:screen_bottom> <div> <wizard:bind></wizard:bind> </div> </wizard:screen_bottom>
<wizard:wizard_bottom> <div> <wizard:bind></wizard:bind> </div> </wizard:wizard_bottom>
</div>
package code
import java.io.File
import scala.xml.XML
import org.specs.Specification
import org.specs.runner.JUnit4
import net.liftweb.common.Full
import net.liftweb.util.PCDataXmlParser
class XmlSourceSpecsTest extends JUnit4(XmlSourceSpecs)
object XmlSourceSpecs extends Specification {
"XML Sources" should {
"be well-formed" in {
/**
* Tests to make sure the project's XML files are well-formed.
*
* Finds every *.html and *.xml file in src/main/webapp (and its
* subdirectories) and tests to make sure they are well-formed.
*/
var failed: List[File] = Nil
def handledXml(file: String) =
file.endsWith(".xml")
def handledXHtml(file: String) =
file.endsWith(".html") || file.endsWith(".htm") || file.endsWith(".xhtml")
def wellFormed(file: File) {
if (file.isDirectory)
for (f <- file.listFiles) wellFormed(f)
if (file.isFile && handledXml(file.getName)) {
try {
XML.loadFile(file)
} catch {
case e: org.xml.sax.SAXParseException => failed = file :: failed
}
}
if (file.isFile && handledXHtml(file.getName)) {
PCDataXmlParser(new java.io.FileInputStream(file.getAbsolutePath)) match {
case Full(_) => // file is ok
case _ => failed = file :: failed
}
}
}
wellFormed(new File("src/main/webapp"))
val numFails = failed.size
if (numFails > 0) {
val fileStr = if (numFails == 1) "file" else "files"
val msg = "Malformed XML in " + numFails + " " + fileStr + ": " + failed.mkString(", ")
fail(msg)
}
numFails must_== 0
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment