This is a post that summarizes how you can integrate Liftweb in an existing Spring-based web application.
The description is based on an actual example project of which the code is available at the Scala Spring project at Google code.
Before we start with the recipe, first some notes about the assumptions for this integration:
Ok, the recipe:
<properties>
<scala.version>2.7.5</scala.version>
<lift.version>1.0.2</lift.version>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-webkit</artifactId>
<version>${lift.version}</version>
</dependency>
<dependency>
<groupId>net.liftweb</groupId>
<artifactId>lift-util</artifactId>
<version>${lift.version}</version>
</dependency>
</dependencies>
See: pom.xml
<filter> <filter-name>LiftFilter</filter-name> <filter-class>net.liftweb.http.LiftFilter</filter-class> </filter> <filter-mapping> <filter-name>LiftFilter</filter-name> <url-pattern>lift/*</url-pattern> </filter-mapping>
See: web.xml
LiftRules.addToPackages("org.springframework.samples.petclinic.lift")
See Boot.scala
<lift:surround with="default" at="content">
<head><title>Owner</title></head>
<lift:OwnerSnippet.add form="post">
<h2><owner:newText/>Owner:</h2>
<table>
<owner:firstName />
<owner:lastName />
<owner:address />
<owner:city />
<owner:telephone />
<owner:submit />
</table>
</lift:OwnerSnippet.add>
</lift:surround>
See ownerForm.html. This particular template uses a default template via the lift:surround element to wrap it in some standard html, but you can organize it any way you like.
class OwnerSnippet {
// Set up a requestVar to track the object for edits and adds
object ownerVar extends RequestVar(new Owner())
def owner = ownerVar.is
def add (xhtml : NodeSeq) : NodeSeq = {
def doAdd () = {
// Reusing the spring validator code
val result = new MapBindingResult(new HashMap(), "owner")
new OwnerValidator().validate(owner, result)
LiftUtils.toLiftErrors(result)
if (!result.hasErrors()) {
try {
LiftUtils.clinic.storeOwner(owner)
S.redirectTo("/owner.do?ownerId=" + owner.id)
} catch {
case e : DataAccessException => error("DataAccessException")
}
}
}
// Hold a val here so that the "id" closure holds it when we re-enter this method
val currentId = owner.id
val submitText = if (owner.isNew) "Add Owner" else "Update Owner"
bind("owner", xhtml,
"newText" -> (if (owner.isNew) "New " else ""),
"id" -> SHtml.hidden(() => owner.id = currentId),
"firstName" -> LiftUtils.field("First Name: ", owner.firstName, owner.firstName = _, "size" -> "30", "maxlength" -> "80", "id" -> "firstName"),
"lastName" -> LiftUtils.field("Last Name: ", owner.lastName, owner.lastName = _, "size" -> "30", "maxlength" -> "80", "id" -> "lastName"),
"address" -> LiftUtils.field("Address: ", owner.address, owner.address = _, "size" -> "30", "maxlength" -> "80", "id" -> "address"),
"city" -> LiftUtils.field("City: ", owner.city, owner.city = _, "size" -> "30", "maxlength" -> "80", "id" -> "city"),
"telephone" -> LiftUtils.field("Telephone:", owner.telephone, owner.telephone = _, "size" -> "20", "maxlength" -> "20", "id" -> "telephone"),
"submit" -> <tr><td><p class="submit"> { SHtml.submit(submitText, doAdd) } </p></td></tr>
)
}
}
Note that in this example we are reusing the validation code that was originally written for Spring (line 10-14).
Also note that it is up to you whether you define your code as a template or snippet. E.g. it would be easy to translate the ownerForm template into a snippet, or vice versa to move more code into the template.
Furthermore, check out the nifty way how Lift enables you to write the add method. What I especially like is the way the type safe way the owner is constructed (lines 4 and 5), how binding works (lines 29 and further ) and the way Scala and Lift allow you to implement a form submit (see line 37 for the call to doAdd and the method definition of doAdd starting at line 9).
On the other side, a Spring controller allows you your dependencies to be injected whereas in Lift you need to call out to obtain the objects you require. For example, in the Spring controller AddOwnerForm.scala we have a setClinic method that injects a Clinic. On the other side, in the Lift snippet we need to call out to the ApplicationContext via the ServletContext to obtain the Clinic object (see line 16 LiftUtils.clinic and it’s implementation).
By the way, there has been an interesting discussion about dependency Injection in Lift. Read that and decide what your opinion is.
Posted: October 19th, 2009 under Java, Programming, web.
Comments: none
©2006 - 2010 Rintcius Blok