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
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
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
Deze tekst in het Nederlands: OnJobs: de nieuwe zoekmachine voor vacatures
I have published a search engine for job vacancies in the Netherlands: OnJobs.
For the techies under us, I have used GWT (Google Web Toolkit) for the client side, Ruby on Rails and Google Custom Search Engine on the server side and Slicehost for hosting.
Have a look at the site and let me know what you think of it!
Posted: November 6th, 2007 under Java, Services & Tools.
Comments: none
Last friday Profict organized a java summer camp. This was the first time that I went there and the first thing that you would notice about the office of Profict is that it doesn’t look like a working environment at all: the office is in fact a beautifully situated castle.
The topic of this summer camp was one that interests me: dynamic languages for the JVM. In the first session Charles Nutter talked about (J)Ruby and Rails and after that it was Graeme Rocher’s turn to talk about Groovy and Grails.
Both Rails and Grails are interesting web frameworks that take the “convention over configuration” principle to heart and drastically increase productivity compared to standard java web frameworks. If you are a Ruby developer I cannot imagine that you haven’t heard about Rails before, but for Java developers that don’t know Groovy and Grails yet: check them out!
Posted: August 29th, 2007 under Java.
Comments: none
Now that Sun has discovered the 4th dimension I thought it was time for a new slogan:
Posted: May 29th, 2007 under Java.
Comments: none
I have been using The Maven Integration for Eclipse version 0.0.10 for some time now and thought it would be useful to share my experiences with it.
In short, version 0.0.10 works quite good for me. Version 0.0.9 had some annoying bugs that made the plugin almost unusable. But these are all solved (or improved) in version 0.0.10 and I am a happy user now.
So if you didn’t like the Maven Integration for Eclipse and tried version 0.0.9 or below, you could give 0.0.10 a try. You probably will like that version a lot better.
The bugs in 0.0.9 that were keeping me from happiness were:
So especially if you recognize one or more of these bugs, I recommend you to upgrade to version 0.0.10 immediately.
See the release notes for a more complete list of changes.
Thanks to the development team (Eugene Kuleshov and Jason van Zyl) for this major quality improvement!
Posted: May 2nd, 2007 under Java.
Comments: none
This post was created from java code. Before I show you this code I will give some background how this post and the code were created.
The following is a transcript of the little Q&A session that was playing in my head:
That depends on how wordpress interfaces with the outside world.
(after some googling…) The wordpress codex mentions some api’s that are supported through xml-rpc.
That’s the same question that is asked on the xml-rpc home page.
This is the answer they give:
It’s a spec and a set of implementations that allow software running on disparate operating systems, running in different environments to make procedure calls over the Internet.
It’s remote procedure calling using HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned.
Furthermore, xml-rpc looks pretty simple looking at the wikipedia examples.
Having scanned through the specs, I can’t find a reason why not, but I really need an implementation to find that out.
The list of implementations at the xml-rpc home page shows a number of java implementations and one of them is from good old apache so I will give that a try.
Ok.
The php code that can be downloaded from dented reality shows the api’s in action. And the actual implementation of these api’s can be found in the xmlrpc.php file which is part of the wordpress distribution.
Ok. Let’s start with a little auxiliary class to keep some state:
package rintcius.blog;
public class BlogInfo {
private String apiKey;
private String userName;
private String password;
private String blogId;
public BlogInfo(String apiKey, String userName,
String password, String blogId) {
this.apiKey = apiKey;
this.userName = userName;
this.password = password;
this.blogId = blogId;
}
public String getApiKey() {
return apiKey;
}
public String getBlogId() {
return blogId;
}
public String getPassword() {
return password;
}
public String getUserName() {
return userName;
}
}
Here’s the class that does the posting:
package rintcius.blog;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
public class BlogPoster {
private static final String POST_METHOD_NAME = "blogger.newPost";
private XmlRpcClient client;
private BlogInfo blogInfo;
private PostType postType = PostType.draft;
public BlogPoster(XmlRpcClient client, BlogInfo blogInfo) {
this.client = client;
this.blogInfo = blogInfo;
}
public void setPostType(PostType postType) {
this.postType = postType;
}
public Integer post(String contents) throws XmlRpcException {
Object[] params = new Object[] {
blogInfo.getApiKey(),
blogInfo.getBlogId(),
blogInfo.getUserName(),
blogInfo.getPassword(),
contents,
postType.booleanValue()
};
return (Integer) client.execute(POST_METHOD_NAME, params);
}
public static enum PostType {
publish(true), draft(false);
private final boolean value;
PostType(boolean value) {
this.value = value;
}
public boolean booleanValue() {
return value;
}
}
}
And finally the example code that made this post happen:
package rintcius.blog;
import java.io.IOException;
import java.net.URL;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import rintcius.blog.BlogPoster.PostType;
import rintcius.util.java.FileUtils;
public class PostExample {
public static void main(String[] args) throws Exception {
// the url of your xmlrpc.php, typically
// of the form http://your.domain.here/wordpress/xmlrpc.php
String xmlRpcUrl = args[0];
// this key is not used in my wordpress version
String apiKey = args[1];
String userName = args[2];
String password = args[3];
// in my wordpress version the blogId is "1"
String blogId = args[4];
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL(xmlRpcUrl));
XmlRpcClient client = new XmlRpcClient();
client.setConfig(config);
BlogInfo blogInfo = new BlogInfo(apiKey, userName, password, blogId);
BlogPoster poster = new BlogPoster(client, blogInfo);
poster.setPostType(PostType.publish);
poster.post(contents());
}
private static String contents() throws IOException {
// According to the wordpress post format the title and
// category id of the post get some special mark up.
return "<title>Look how this wordpress post got created from java!</title>"
+ "<category>6</category>"
+ FileUtils.getContentsOfResource("rintcius/blog/post.txt");
}
}
… or was it this post making the code happen?
Posted: July 16th, 2006 under Java.
Comments: none
©2006 - 2010 Rintcius Blok