Groovy HTML
No, that's not "cool" HTML, but HTML ala Groovy. This week I had my first experience writing Groovy for HTML and I thought I'd share my thoughts. I just want to warn folks that a) I'm a rank newbie at Groovy and b) any code I show is probably horrible and inefficient. With that being said, let me just say first off. The experience of HTML is Groovy is... odd. The only thing I can compare it too is writing by using a mirror instead of actually watching your hand. While it is certainly not that hard, not hard at all really, it's just unlike anything I've done before!
Before I show the code, there are two concepts I have to cover. I'll repeat the warning I gave above. I learned about both these things over the past few days. Both features really deserve a lot more explanation then I'm giving it, but for those who know nothing about Groovy I want to give a bit of context behind what I'm doing.
The first concept is that of the Groovlet. A Groovlet is just a fancy way of saying a Groovy script written for a web site. If you know what a JSP file is, this is the same thing. Us CFers don't really ever think about this since all our scripts (the views anyway) are for web based consumption, but Groovy, like Java, can have multiple uses of the code. A web server using Java is just a specialized client. It has certain parameters (request, response, etc) for the HTTP request that ColdFusion always has access to due to it's very nature. Writing a Groovlet is like writing any other Groovy script except that you have access to built in variables (again, request, response, etc) to help you work with and respond to the HTTP request. Think of the URL scope in CF. In a Groovlet I have a params object that acts the same. (Although if I read it right, it has both URL and Form scopes rolled into one, like a Model-Glue Event.) Anyway, the essential point is - think of a Groovlet as simple a Groovy script for the web.
The second concept is a builder. Now - I really dig Groovy - and the reason why is that one of the guiding principals seems to be "If folks do this a lot, lets make it easier." This is something I've always appreciated in ColdFusion, and while I can respect other platforms (even .Net and PHP), no one else seems to get this simple concept! I'd take cfdump over interfaces any day of the week. (By the way, I was pleasantly surprised to see dump() supported in Groovy!) Some of these features are expressed via syntax shortcuts. Those are nice and all, but not earth shattering. I compare it to how CF8 added += and &=. Builders are something else. In all my years of programming I don't think I've seen anything even remotely like it. (Although I believe the concept is based on earlier languages.) Builders solve the problem of building complex, nested structures in a way that the code actually represents the final result. I'm not sure I expressed that right, but take the following CFML as an example. It outputs a simple XML string:
<cfsavecontent variable="result">
<cfoutput>
<cfloop index="x" from="1" to="3">
<invoice id="#x#">
<cfloop index="y" from="1" to="5">
<lineitem product="#y#" quantity="1">
</cfloop>
</invoice>
</cfloop>
</cfoutput>
</cfsavecontent>
<cfoutput>#htmlCodeFormat(result)#</cfoutput>
Notice how I've mixed in the raw XML (invoice, lineitem) along with CF control structures. If you think about it, that's kind of handy as a reader can get an idea of the final result by just looking at the code. They can see the nesting. They can see the loops and visualize the final result, even if x and y were more dynamic. But what if you wanted to take the same code and create an array of structures instead?
<cfset invoices = arrayNew(1)>
<cfloop index="x" from="1" to="3">
<cfset invoice = arrayNew(1)>
<cfloop index="y" from="1" to="5">
<cfset lineitem = structNew()>
<cfset lineitem.product = y>
<cfset lineitem.quantity = 1>
<cfset arrayAppend(invoice, lineitem)>
</cfloop>
<cfset arrayAppend(invoices, invoice)>
</cfloop>
<cfdump var="#invoices#">
Not quite so friendly, is it? Because we are dealing with data now we have to use an API to add the children to the parents. Visually it isn't quite as simple to grok either. This is where Groovy's Builder support comes in. It can take any arbitrary structure of code and create a result object from it. That result could be XML (or HTML) or it could be an object. What really rocks is - imagine if my first CFML example could be converted from XML to a structure in one line of code? (Technically, I could wrap it in cfxml and get an XML object. Just pretend CF isn't so darn useful. ;) In Groovy, it's just a matter of changing the builder.
Now I know I'm giving short shrift here to what is a huge topic (and again folks, I'm new at this, so please forgive any dumb mistakes!) but lets bring this back to the original topic - HTML in Groovy. As I mentioned with Groovlets, each Groovy script is provided with a set of default variables. One of those is automatic support for an HTML builder. This lets me output HTML to the screen using builder syntax. I can still output using println of course, but the builder syntax is a bit more clean. Consider the following script:
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.broadchoice.bcp.services.AdminService;
import com.broadchoice.bcp.model.beans.Account;
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(context);
//get the account service so we can list all accounts
AdminService adminService = webApplicationContext.getBean('adminService');
def accounts = adminService.getAccounts();
html.html{
head {
title 'Account Management'
}
body {
h1 'Accounts'
p "There are currently ${accounts.size()} accounts."
if(accounts.size() > 0) {
table(border:1) {
tr {
th 'Name'
th 'Description'
}
accounts.each { item ->
tr {
td {
a(href:'account.groovy?accountid='+item.id,item.name)
}
td item.description
}
}
}
}
p {
a(href:'account.groovy','Add Account')
}
}
}
There is a lot in here, but focus on the html.html portion. Notice how I build out a set of nested HTML tags. For entities that don't wrap anything, like my first h1, the syntax is very short: h1 'Accounts'. This comes out as <h1>Accounts</h1>. Basically I wrote: "Do an H1 tag and this is the content." For tags that have both content and arguments, it is a bit more complex. (It took me a good hour to figure this out. No one said I was fast...) My link towards the bottom has both an href and content: a(href:'account.groovy','Add Account'). Notice that this looks a bit like named arguments in CFML, but we don't have a name for the second argument! Groovy assumes than that unnamed argument is simply the content of the tag. (This could be a good solution for eventually porting all of CFML to script syntax.)
Also look at the nesting. My table (yes, I used tables, I laugh in the face of CSS) begins with an outer table element with TRs and TDs inside it. What's kinda cool about this is that it would be - as far as I know - impossible to write incorrectly nested HTML. The drawback to this is that supporting something like this:
This is a <b>cool</b> and <i>interesting</i> blog post.
gets more complex as you have to break things out more. That line in Groovy would be:
p {
span 'This is an '
b 'cool'
span ' and '
i 'interesting'
span 'blog post'
}
But outside of that, I'm finding writing HTML to be... well... kinda cool. The last time writing HTML was cool was back when Mosaic was king. It's almost like having a cfscript version of HTML at my disposal.
All in all - a pretty fun experience. What has not been fun is dealing with JBoss and the server in general. I know I've said this before, but ColdFusion has really spoiled in terms of allowing me to focus on the code and not deployment. Is ColdFusion the only server out there that makes this simple? Do Java people really deal with this kind of junk on a daily basis?

p { "This is a <b>cool</b> and <i>interesting</i> blog post. "}
While it wouldn't be structured, I would doubt the Groovy is actually parsing the string for tags (unless of course if it's automatically escaping characters.)
p("....")
you get the HTML escaped.
I believe { } is only used when you will have child nodes.
You get the same result with p "..." as well.
html = { element:"div",
attributes { id:"mydiv", class="someclass" },
children [
{ element="a", attributes { href="somelink" }, children ["link text"] },
{ element="img", attributes { src="somepic" } }
]
}
You would lose some of the framework's shortcuts for generating things (AJAX widgets, node variables and XSL skins primarily), but deserializeJSON would probably execute a good deal faster than calling the XHTML tag. Certainly an interesting experiment. :)
Even tomcat has hot swap.
I would be extremely surprised if large java shops like Atlassian redeploy on every save just to see the results of their work.