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
I have been following Scala for some time now and while it looks very promising, I didn’t get any further than reading tutorials and using the scala eclipse plugin for a few tryouts…. until just after Christmas when I got directed to Project Euler after reading Jeff Moser’s “How the legacy of a dead mathematician can make you a better programmer”. To get an idea what project Euler is about, I’ll quote from their website:
Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems.
The motivation for starting Project Euler, and its continuation, is to provide a platform for the inquiring mind to delve into unfamiliar areas and learn new concepts in a fun and recreational context.
This got me started in Scala. And indeed, it has been fun for me. Not only because it dusts off my math but also because I like this way of learning a new language. If you have a little background in math and computer science you will find that the problems start quite easy and don’t require much code, which gives you the opportunity to experiment with the Scala language and API in a playful way while at the same time moving forward.
For me this way of actively working with a language has proven much more effective than just reading through example code. It just better sticks in my brain. Do you have a similar or totally different way to learn a new language? Let me know!
For the curious people: at the time of writing I have solved the first 17 problems (12 jan 2008).
Update: When listening to episode 158 of the Javaposse I heard that Jorge Ortiz did exactly the same thing. He also gives his solutions to a few of the puzzles so if you want to get a feeling of Scala and/or project Euler take a look there.
Posted: January 12th, 2008 under Java, Programming.
Comments: none
©2006 - 2012 Rintcius Blok