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
Of the many ways of writing a DSL in groovy I prefer the approach that is taken in
a Groovy DSL from scratch in 2 hours. That article describes a general way to create a DSL and you don’t have to write too much code for it. Moreover it takes the groovy Script as a base of the DSL which is really quite powerful. But there’s still too much unnecessary complexity that you will have to deal with if you want to create a DSL (see the code dealing with ExpandoMetaClass, closures and delegates in the article).
The goal of my experiment is to further simplify creating a DSL. I want to adapt groovy Scripts in such a way that it becomes easy to access the parts of a script and use them to construct your DSL.
For this reason I choose to combine scripts with Expando’s in such a way that closures become accessible as Expando’s in a recursive way. The class that adapts scripts like this is ExpandoDsl.
This post shows what you have to write to create a DSL using (the current version of) ExpandoDsl. I will simply take the architecture example from a Groovy DSL from scratch in 2 hours so it’s easy to compare the code you have to write. Note though that I didn’t rewrite the architecture DSL completely, but it’s enough to make Steven’s example working and it should give you a good idea of what you need to write to create a DSL.
Here is the code:
package nl.rintcius.example.dsl.architecture
import com.seventytwomiles.architecturerules.configuration.Configuration
import com.seventytwomiles.architecturerules.domain.SourceDirectory
import com.seventytwomiles.architecturerules.domain.Rule
import com.seventytwomiles.architecturerules.services.CyclicRedundancyServiceImpl
import com.seventytwomiles.architecturerules.services.RulesServiceImpl
import org.apache.log4j.*
import nl.rintcius.groovy.ExpandoDsl
public class GroovyArchitecture {
static void main(String[] args) {
BasicConfigurator.configure()
LogManager.rootLogger.level = Level.INFO
runArchitectureRules()
}
static void runArchitectureRules() {
runArchitectureRules(new File("architecture.groovy"))
}
static void runArchitectureRules(File dsl) {
Expando root = new ExpandoDsl(dsl.text).create()
Configuration configuration = createConfiguration(root.architecture)
new CyclicRedundancyServiceImpl(configuration).performCyclicRedundancyCheck()
new RulesServiceImpl(configuration).performRulesTest()
}
static Configuration createConfiguration(Expando expando) {
Configuration configuration = new Configuration()
configuration.doCyclicDependencyTest = true
configuration.throwExceptionWhenNoPackages = true
expando.properties.each() { key, value ->
if (key == "jar") { configuration.addSource( new SourceDirectory(value.value, true)) }
else if (key == "rules") { createRules(value).each() { rule -> configuration.addRule(rule)} }
}
configuration
}
static List createRules(Expando expando) {
expando.properties.collect() { key, value ->
createRule(key, value)
}
}
static Rule createRule(String ruleName, Expando expando) {
Rule rule = new Rule(ruleName)
expando.properties.each() { key, value ->
if (key == “comment”) { rule.comment = value }
else if (key == “violation”) { rule.addViolation(value.value) }
else if (key == “package”) { rule.addPackage(value.value) }
}
rule
}
}
As you can see, the code is quite easy to follow. All you have to do is build the root Expando via and then traverse the Expando’s via expando.propertes and build your structure.
new ExpandoDsl(text).create()
Finally, apart from ExpandoDsl there’s also ExpandoBuilder if you prefer the more restrictive builder syntax.
Let me know what you think of it!
Posted: September 24th, 2009 under Java.
Comments: none
Need to do custom RPC serialization for a class in GWT?
Here’s how. E.g. for the class my.example.MyObject create a class named my.example.MyObject_CustomFieldSerializer. And then implement
public static void serialize(SerializationStreamWriter streamWriter, MyObject myObject)
throws SerializationException {}
public static void deserialize(SerializationStreamReader streamReader, MyObject myObject)
throws SerializationException {}
//This method is optional
public static MyObject instantiate(SerializationStreamReader streamReader)
throws SerializationException {}
For more info, see CustomFieldSerializer (somehow this page didn’t show up when I googled for it, only after I knew the term was CustomFieldSerializer).
Posted: August 27th, 2009 under Java.
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
Next to searching from the Lenzcape application, you can also use the search plugin to search directly from the browser’s searchbar. This is how I am using Lenzcape myself usually.
The searchbar is particularly easy when you know the area that you want to search (that’s the lenz in lenzcape’s terminology). Further, the more you need to search in a specific area, the more it will pay off to create a lenz for that area.
Lenzcape’s searchbar in Firefox
To illustrate what I mean, let’s take grails as an example. I used grails to develop Lenzcape, so I am often searching grails related stuff. The base lenz for grails is “dev/grails” and following the search syntax you separate the lenz part of the query and the terms that you want to search for with a “)”. In this way you can type dev/grails ) redirect in the searchbar and it will search for redirect just in the grails area.
But you can also search more specific grails topics such as:
These lenzes all work for you as well because they are predefined. But you can also extend lenzes by integrating them with your own bookmarks. For example, I have included a few grails blogs with tag dev/grails/blog to my personal bookmarks. In this way I can search my bookmarked grails blogs via dev/grails/blog ) redirect. Note that if you type this using the search bar you will get no results unless you have also added bookmarks with tag “dev/grails/blog”.
Posted: April 27th, 2009 under Lenzcape.
Comments: none
In a former post I wrote that I would show how you can build your own lenzes in Lenzcape.
Initially I intended to show it in a blog post, but later when I got the idea to make a live demo, I thought it would be clearer (and cooler) to include it in the live demo. So check out the live demo if you want to see how you can build your own lenzes!
Posted: April 24th, 2009 under Lenzcape.
Comments: none
I have been busy redesigning Lenzcape. After the initial tryout version, I think the current state of this version is beta. Have a look at it and make sure you don’t miss the live demo.
Thanks to everyone who provided me feedback about the initial version. This has been really helpful to me. I look forward to hear what you think about this new version.
Posted: April 22nd, 2009 under Lenzcape.
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: 3
The traditional tools that are used to find your little gem on the web are the general search engine and the bookmark manager. With Lenzcape you can combine the power of bookmarking and searching. It allows you to search through the pages of your favorite, bookmarked sites in such a way that you are able to find your gem more effectively and efficiently. An example is probably the best way to understand how this is done exactly. So let me explain via an example.
Let’s take recipes as an example and suppose that we want to try out a new recipe with spinach tonight.
We will first discuss how that is usually done (i.e. via a general search engine, your bookmarks or combination of those). And then I’ll show you how you can improve on this using Lenzcape.
Probably, the first thing you will do is go to your favorite search engine and type something like “recipe spinach”. The results at google will show you all kinds of recipe sites of which most of them will actually contain recipes.
But you recognize the problems:
And then finally you will have your recipe.
If cooking is a hobby of you then you will probably also have bookmarked some of your favorite recipe sites. So you can look up these bookmarks in your bookmark manager and search for some recipes from there. The advantage of using bookmarks over the search engine is that you know that these are all quality recipe sites and that each of them will lead you to good candidate recipes. So no rubbish sites to browse through. You may even know the structure of these sites so you will get to the recipes faster.
But there are still some major problems:
Now compare this with how you will find spinach recipes via Lenzcape. This is the first page that Lenzcape returns.
You can see it live here

See the difference? Lenzcape immediately returns spinach recipes, the exact information that you are looking for! No need to go to several sites and separate the garbage from the gems. All you have to do is pick your recipe.
The advantages of using Lenzcape:

The screenshot shows that there’s a soup and a dessert lenz under my recipes.
This shows another of Lenzcape’s features: you can zoom in for more specialized searches and zoom out for more general searches.
For example, these are the results when you are looking for spinach soups. You see that all the main dishes with spinach are gone, just soups with spinach are returned.
(See it live here)

Lenzcape is not meant for all types of searches. Generally, topics that you don’t bother to have any bookmarks for, you will probably also not need a special search engine for (although there may be a popular lenz defined for that).
In contrast, it is a tool that makes the pages of your bookmarked sites fully searchable. Where Lenzcape shines are topics that you often need to get back to, either for your profession or hobby. On these topics you typically will have bookmarks. And the more bookmarks you have on these topics, the more advantageous Lenzcape is.
Other examples are:
All of these are already included in the Lenzcape application, ready to be used.
In the next post I will show you how you can create and manage lenzes with Lenzcape (Update: this is now part of the live demo). It is really not difficult, it’s very much like bookmarking, but there are a few things that you should know to make full use of Lenzcape.
It is also not a lot of work to get started. My recipe search engine that was used for this example contains just 15 bookmarks and that’s including the dessert and soup sublenzes.
By the way. I have added the recipe lenz as a popular lenz on Lenzcape application (hobby > recipe). Bon appetit!
Posted: December 12th, 2008 under Lenzcape.
Comments: 1
©2006 - 2012 Rintcius Blok