A recipe to integrate Lift in an existing Spring-based web application

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:

  • This recipe assumes Lift 1.0.2 and is about putting Lift’s webkit module to use (Lift also has modules for data access for example, but we will still use Spring for data access).
  • It also assumes that all Spring objects that the Lift-based code needs to access are available in the root Spring ApplicationContext. So in the example project they are available in applicationContext-jdbc.xml as opposed to the servlet specific ApplicationContext petclinic-servlet.xml.

Ok, the recipe:

  1. Specify the necessary dependencies.
            <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

  2. Add a filter and filter-mapping to the web.xml. For example:
    	<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

  3. In Lift’s Boot class configure where Lift should look for snippets. For example:
    LiftRules.addToPackages("org.springframework.samples.petclinic.lift")

    See Boot.scala

  4. Create a Lift template
    <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.

  5. And finally a snippet:
    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.

Further simplifying creating groovy DSL’s

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
new ExpandoDsl(text).create()
and then traverse the Expando’s via expando.propertes and build your structure.

Finally, apart from ExpandoDsl there’s also ExpandoBuilder if you prefer the more restrictive builder syntax.

Let me know what you think of it!

Per class custom serialization in GWT

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).

Getting the class attribute of an element in GWT

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…

Euler meets Scala - Fun way to learn a new programming language

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.

OnJobs: a new job vacancy search engine

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!

Summercamp: Rails and Grails


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!

Photos and more information on this summercamp.

Sun’s new slogan: Write once, run anytime

Now that Sun has discovered the 4th dimension I thought it was time for a new slogan:


Write once, run anywhere

+

When, not where

=

Write once, run anywhentime

Short review of Maven Integration for Eclipse version 0.0.10


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:

  • “Unable to index” error - This bug made me have to restart Eclipse just about every time I changed something in the pom.xml. Quite a relief that this bug is fixed now.
  • Issues with hierarchical projects - I have a few hierarchical projects and these did not work because of these bugs. In version 0.0.10 I can use hierarchical projects without a problem.
  • Issue searching libraries - Searching libraries was confusing the hell out of me in 0.0.9. It still does not work perfectly, but it is a lot better now. See details in the bugreport for the remaining issue.
  • An issue related to dependency management. I couldn’t match this with a bug in the release notes, but this issue is also solved now. This issue related to dependency management: When a project A used another project B then only libraries specified in project B were picked up in project A. So I had to specify all libraries in project B.

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!

Look how this wordpress post got created from java!

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:

How can you manage a wordpress blog residing at a webhost from home with java?

That depends on how wordpress interfaces with the outside world.

So how does wordpress interface with the outside world?

(after some googling…) The wordpress codex mentions some api’s that are supported through xml-rpc.

What is 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.

Apart from looking simple, would it also be usable?

Having scanned through the specs, I can’t find a reason why not, but I really need an implementation to find that out.

Ok, which implementation are you going to use?

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.

Show me some code.

Ok.

Back to wordpress. What functionality do these api’s expose?

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.

Time for some java?

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? ;-)

©2006 - 2012 Rintcius Blok