10 May, 2009
Gracelets and Seam – a DSL for Facelets and Groovy with easy integration
Posted by: TheKaptain In: Development
Over the last year I’ve done a lot of work with JBoss Seam, and while it’s not Grails it’s also not that bad for a web framework. Facelets is the view technology of choice, and it’s certainly better than many alternatives, but at the heart it is still xml and all those brackets make me dizzy after awhile. Along comes Gracelets to provide a nice builder DSL and Groovy integration as a replacement for my xml woes. Yay! It also brings some great simplification to the creation of component libraries – including hot deployment. But enough of the sales pitch, let’s see if it works.
In order to test drive Gracelets, I took an existing Seam web-app and configured the web.xml with the GraceletsViewHandler in place of the standard SeamListener. I generally use Maven for dependency management, and I couldn’t find a repository hosting Gracelets so I installed the downloaded jars into my local repository and adding them to the web-app. The JBoss Seam Extension is also required.
[bash]
mvn install:install-file -Dfile=gracelets-api-2.0.0.jar -DgroupId=gracelets -DartifactId=gracelets-api -Dversion=2.0.0 -Dpackaging=jar -DgeneratePom=true
mvn install:install-file -Dfile=gracelets-impl-2.0.0.RC2.jar -DgroupId=gracelets -DartifactId=gracelets-impl -Dversion=2.0.0.RC2 -Dpackaging=jar -DgeneratePom=true
mvn install:install-file -Dfile=jboss_seam_2.0.0_all-1.0.11.jar -DgroupId=gracelets -DartifactId=jboss-seam-extension -Dversion=1.0.11 -Dpackaging=jar -DgeneratePom=true
[/bash]
[xml language=”true”]
<dependency>
<groupid>gracelets</groupid>
<artifactid>jboss-seam-extension</artifactid>
<version>1.0.11</version>
</dependency>
<dependency>
<groupid>gracelets</groupid>
<artifactid>gracelets-api</artifactid>
<version>2.0.0</version>
</dependency>
<dependency>
<groupid>gracelets</groupid>
<artifactid>gracelets-impl</artifactid>
<version>2.0.0.RC2</version>
</dependency>
[/xml]
The application was deployed as usual and fired up without a problem. For a test page I just created an index.groovy file in the root directory. According to the docs, a .groovy extension trumps .xhtml so that effectively replaced the front page of the app. Here’s the standard first page of a new web-app(straight from the Gracelets examples), with the xhtml builder.
[groovy language=”true”]
xh.html {
head { title("Hello World Example") }
body {
print { "Hello World @ " + new Date() }
}
}
[/groovy]
Not bad, let’s compare to the standard Facelets version, using a file based on the standard seam-gen created index.xhtml file. I’ve bound the instantiation of the Date object to a backing bean, since you can’t make an inline call to do it a standard Facelets view. I seem to recall seeing that Seam kept a component available to provide the present Date/Time, but I couldn’t find it offhand today.
[xml language=”true”]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view contentType="text/html"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:s="http://jboss.com/products/seam/taglib">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Hello World Example</title>
<ui:insert name="head"/>
</head>
<body>
Hello World @ #{backingBean.date}
</body>
</html>
</f:view>
[/xml]
Notice I’ve also left the Seam and RichFaces tab library namespaces in the xml declaration. Although the Gracelets docs didn’t seem to easily confirm this, inclusion of the JBoss Seam extension also makes those libraries and their associated builders available by default for Gracelets views. Here’s a final example to leave you with that incorporates a couple of elements from those libraries and a quick and dirty use of .each for rendering, and even a couple of screenshots to show off the progression.
[groovy language=”true”]
def loremIpsum = ”’
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin tempor, mauris sed volutpat consequat, risus tellus ultrices
tortor, at sollicitudin felis erat vitae augue. Pellentesque habitant morbi tristique senectus et netus et malesuada fames
ac turpis egestas. Vestibulum tincidunt egestas viverra. Integer ullamcorper, ipsum id malesuada sollicitudin, nisl velit
ultricies purus, eu aliquet diam mi sit amet eros. Quisque arcu orci, consequat dictum vehicula a, pellentesque eu nisl.
”’
xh.html {
head { title("Hello World Example") }
body {
s.div(id:’aSeamDiv’, rendered:’true’) {
r.panel(header:’A RichFaces Panel’) {
println { "Hello World @ " + new Date() }
a(‘MyBlogLink’, href: ‘http://www.kellyrob99.com/blog’)
}
}
r.separator()
r.spacer()
r.simpleTogglePanel(header:’A RichFaces TogglePanel’){
println loremIpsum
}
def tableModel = loremIpsum.tokenize()[0..10]
def tableModel2 = loremIpsum.tokenize()[11..20]
table {
tr {
td {
tableModel.each { println it }
}
td {
tableModel2.each { println it }
}
}
}
}
}
[/groovy]
Not bad at all. I won’t bore you with the equivalent xml version – suffice it to say it takes up a lot more space. I haven’t even touched on the easy component/library features Gracelets provides yet, but I am already quite impressed simply by the replacement of xml with an equivalent but sparser syntax. And I don’t miss the need for closing tags much either. The documentation for the project is quite complete, rich with examples, at least for the standard jsf components(hint hint – more examples using Seam and RichFaces would be appreciated!) Give it a try and decide for yourself, but if it keeps going this way, it might become a reasonable alternative for Grails.
π
[nggallery id=3]