JRubyVelocity tools 19 January 2007 Reactions

I had a need yesterday to play around with velocity in order to explore some stuff on templating and macros. I like velocity's simple template language, but this was one of those times where I wasn't using it in the context of some Java or .NET work. At that point working with velocity becomes a bit of a pain as you have to setup the context and run the processor in Java.

This kind of situation calls for a scripting language, my preferred scripting language is Ruby, and thus I thought this was a great case for trying JRuby. My conclusion is that it works a treat, but I'll bore you with the details.

I downloaded JRuby and unpacked it in /usr/local/lib with a symlink so I could get to it with /usr/local/lib/jruby.

I then put a simple redirecting shell into /usr/local/bin

JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun
JRUBY_HOME=/usr/local/lib/jruby

/usr/local/lib/jruby/bin/jruby "$@"

I could then run JRuby.

$ jruby -v
ruby 1.8.5 (0) [java]

(Actually it took me ages to get that to work, I eventually found the bug between the chair and the keyboard. I'm too embarrassed to tell you what it was.)

To run velocity you have to add it to JRuby's classpath.

CLASSPATH=path/to/velocity-dep-1.4.jar
export CLASSPATH
jruby "$@"

To help run velocity I wrote a little helper class.

require 'java'

class VelocityLauncher
  def initialize context, template
    @context = context
    @template = template
  end

  include_class 'org.apache.velocity.app.Velocity'
  include_class 'org.apache.velocity.VelocityContext'
  include_class 'java.io.StringWriter'

  def run
    vc = VelocityContext.new(@context)
    writer = StringWriter.new
    Velocity.init
    Velocity.evaluate(vc, writer, "LOG", @template)
    return writer.getBuffer
  end
end

Now I can take write a little template:

This is an announcement from $host

Our chief weapons are:
#foreach ($w in $weapons) 
  - $w 
#end

To populate it, all I need is a ruby hash, which is easy to make.

ct = {'host' => 'Cardinal Fang', 
  'weapons' => ['Fear', 'Surprise', 'Ruthless Efficiency']}
template = File.readlines('template.txt').join

puts VelocityLauncher.new(ct, template).run

I can imagine extending this to a nice command line runner for velocity which would take a context file of the form:

host = 'Cardinal Fang'
weapons = ['Fear', 'Surprise', 'Ruthless Efficiency']

But I don't need that yet, so I'll do it another day (and I'm pretty sure what the binding for 'another day' is).


Links
home
bliki
feed 
Translations
Japanese
Spanish
Korean
Chinese
Thai
Categories
agile
design
dsl
leisure
refactoring
ruby
thoughtWorks
tools
uml
writing
Blog Roll
ThoughtBlogs
TW Alumni
Nicholas Carr
Steve Cook
Brian Foote
Simon Harris
Gregor Hohpe
/\ndy Hunt
Ralph Johnson
Patrick Logan
David Ing
Brian Marick
Jeremy Miller
Jimmy Nilsson
Samuel Pepys
Keith Ray
Johanna Rothman
Kathy Sierra
Dave Thomas