Barbler: Integrating JRuby Warbler into Apache Builder

After having used Apache Builder for a week and extracted our Warbler-code into a bonafide extension, I'm sharing it with the community under the fetching name Barbler.

Barbler integrates itself between the build and packaging stages of the Apache Builder lifecycle and makes calls into Warbler to automate WAR-file creation. Now Warbler does a really good job for packaging standalone Rails apps. Unfortunately I needed something more integrated into our application build process, that pulls in our Spring Framework-based Java code, Scala code, and Rails application and produces a single WAR-file containing all dependent libraries, Rails code, XML deployment descriptors and Java class files. Apache Builder does everything other than the Rails-packaging. Barbler steps to provide that missing step.

Create a barbler.rb file in your project folder, which also contains your buildfile and copy the following contents into it:

# Barbler  
# is an Apache Builder extension to integrate the JRuby Warbler gem.
# For tips on how to use Barbler checkout http://www.denofubiquity.com/ruby/barbler/
# 
# This code is licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0.txt)
# Please distribute Barbler code with this code intact.
# (c) Ijonas Kisselbach 2009

require 'warbler'

module Barbler  
  include Extension

  first_time do
    # Define task not specific to any projet.
    desc 'Warbles Rails sourcecode tree into a staging folder'
    Project.local_task('warble' => 'build') { |name| "Warbling #{name}" }   
  end

  before_define do |project|    
    project.task('warble'=>project.task('build'))
    project.group ||= project.parent && project.parent.group || project.name
    project.version ||= project.parent && project.parent.version    
  end

  # To use this method in your project:
  #   warble(:rails => path_to(:rails), :tasks => [:app, :public])
  def warble(*args)
    options = args.pop
    rails_path = options[:rails]
    warble_tasks = options[:tasks]

    # Define the warble task for this particular project.
    Rake::Task.define_task 'warble' do |task|
      # get all the important components from the Rails GUI into the staging directory
      puts "Warbling #{rails_path}"
      Dir.chdir(rails_path) do
        warble_cfg = eval(File.open("config/warble.rb") {|f| f.read})
        Warbler::Task.new(:war, warble_cfg)
        warble_tasks.each {|task| Rake::Task["war:#{task}"].invoke}
      end
    end
  end

end

class Buildr::Project  
  include Barbler
end

Add the folllowing line to the top of your buildfile:

warble(:rails => path_to(:rails), :tasks => [:app, :public])

You can then define your warble task using the following line

warble(:rails => path_to(:rails), :tasks => [:app, :public])
whereby the first parameter is a path string to where your Rails code is located. You may locate your code in src/main/rails in which case you'd use
warble(:rails => path_to(:source, :main, :rails), :tasks => [:app, :public])

The second parameter is the list of Warbler tasks that you'd like to have executed. See the Warbler documentation for more help, or check out the Warbler source code - it's very readable.