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
Just played around a bit with WolframAlpha.
I can see it has added value especially for scientists and engineers. It’s a kind of Mathematica with a web front end and a large dataset to obtain the information from. Its use will largely be depending on the quantity (and quality of course) of the underlying dataset. To give you an impression of its current state, the data it has of Balkenende (Prime Minister of the Netherlands) is still limited (what is his salary?) and nothing compared to the data that is provided on Wikipedia.
On the other hand, it’s quite nice to be able to quickly see some math plots and it’s also good in doing conversions and quick calculations such as 3 feet or time in tokyo.
All in all, I think I will use WolframAlpha every now and then as a companion to Wikipedia.
Posted: May 18th, 2009 under Services & Tools, web.
Comments: none
After the old NKS, Wolfram is about to present another (and better?) NKS version to the world. A new kind of search that is surely making me curious! Hope it will live up to my expectations when it’s getting live.
See this preview (the video is low quality but gives an impression).
Posted: May 2nd, 2009 under Services & Tools, web.
Comments: none
Spent a while on solving this one…
For the new version of my GWT application, I needed to get the class attribute of an element.
This code was working fine in Firefox:
HTML html = new HTML(text);
NodeList links = html.getElement().getElementsByTagName(”a”);
for (int i = 0; i < links.getLength(); i++) {
com.google.gwt.user.client.Element link =
(com.google.gwt.user.client.Element) links.getItem(i);
Log.info(link.getAttribute("class"));
}
However, when I started testing other browsers this appeared not to work in Internet Explorer.
So I started trying some alternatives:
Log.info(DOM.getElementAttribute(link, "class"));
// Chrome & FF: ok IE: ""
Log.info( DOM.getElementProperty(link, "class"));
//Chrome, FF& IE: null
Log.info(link.getAttribute("class"));
//Chrome & FF: ok IE: ""
Log.info(getAttribute(link, "class"));
//Chrome & FF: ok IE: null
Log.info(link.getClassName());
//Chrome, FF & IE: ok
}
public static native String getAttribute(Element elem, String attr)
/*-{
return elem.getAttribute(attr);
}-*/;
At last link.getClassName() did the trick, but it took me some time before I realized that class is treated as an exceptional attribute in IE and that this method did exist at all!
Would be nice if there was a mechanism (assert?) that pointed to this method when getAttribute is called with class (and what about id?). But for now I hope google is your friend when you stumble on this issue…
Posted: April 18th, 2009 under Java, web.
Comments: 2
©2006 - 2010 Rintcius Blok