As a way to blow off some steam, I like to contribute to open source software</a>. You might ask why, as a software developer who spends his entire day writing code would I want to spend my free time writing more software. I honestly don't know the answer to that question. I find something enjoyable in giving something back, or something along those lines.
Anywho, one of the projects that I contribute to and have talked about on here before is the Jenkins</a> continuous integration server. Jenkins uses an MVC model for displaying webpages and interacting with the API of the application, the views are created by using Jelly</a>. I will be completely honest, I hate creating and using Jelly views. Whoever thought up "executable XML"...
I found out that you could also do views using Groovy</a>, so basically you just use scripting when you want and use the tag libraries like you would from Jelly, but get this, it doesn't suck!
I wrote a little utility to convert Jelly views to Groovy views, because when I found out I could convert the views in the email-ext</a> plugin to Groovy from Jelly, I wanted to do it immediately, but who wants to convert by hand! We're software developers, we don't do things by hand. We'll spend twice as long to write a tool as it would take to do it by hand, but then, by George, if we have to do it again, it will take milliseconds!
So, the tool is strangely called jelly2groovy</a> because you have use that naming format when writing a tool like this, just in case you didn't know that. I was converting the views in the email-ext plugin from Jelly to Groovy and the following code was generated.
[groovy]
f.entry(title:_("Default Subject"), help: "/plugin/email-ext/help/projectConfig/defaultSubject.html") {
if(instance.configured) {
input(name: "project_default_subject", value: instance.defaultSubject, class: "setting-input", type: "text")
}
else {
input(name: "project_default_subject", value: "$DEFAULT_SUBJECT", class: "setting-input", type: "text")
}
}
}
[/groovy]
The thing to notice in that code is the double curly brace at the end. I only have one place that outputs a closing curly brace in the conversion script.
[groovy]
if( doOutput && (elem.children().size() > 0) ) {
out.writeLine("${' ' * indent}}")
}
[/groovy]
I set doOutput to either true or false depending on if the tag I am rendering needs it or not (the Jelly choose tag doesn't need to be rendered, just the when/otherwise children).
So, somehow, doOutput was getting set to true, even though I set it to false inside the check for the 'choose' tag element.
Wha?!
The code is basically like this:
[groovy]
doOutput = true
...
if(tag == 'choose') {
doOutput = false
}
...
// iterate over children by calling the current method recursively
if(doOutput...) {
// generate the closing curly brace
}
[/groovy]
Not very complex. It turns out though that there is a subtle issue with the way I wrote the code and it all lies in a three letter keyword 'def'
Once I figured that out, I added 'def' in front of some key variables, and things worked perfectly.
jelly2groovy is now working on several tags and does a good job of converting things over, obviously there are still tags I don't handle and things I haven't tried yet (taglibs!) but its coming along nicely.