Ruby in Java, Java in Ruby, JRuby or Ruby Java Bridge?

Hosting (J)Rails applications on a high availability Java infrastructure with clusters, loadbalancers and all that shit stuff is great, if you already have it in place.

But does running an app on the JRE make it a JRuby application by default? Do you really want to be stuck on JRuby?

I really like the idea of running code with the most appropriate runtime available, that is why I use RVM all the time. JRuby is still very slow on startup and tools like autotest/autospec take minutes for just a handfull of tests…

So I would like to host Rails applications on a Tomcat, but on the other hand I want the tests to be executed with MRI! This should not be a problem as long as you don’t want to share a common codebase within Ruby and Java.

Integration

Is there a best practice for combining Java and Ruby?

Since every project is different, I think that you’ve got to evaluate the possible solutions to pick the one that fits best.

The next sections cover some approaches on integration of Java and Ruby code. Make sure to have RVM installed if you want to execute the provided example code. I assume that a JRE is provided with every OS nowadays…

Java in Ruby

There are two common solutions for embeding Java into a Ruby application. The first and obvious one is via JRuby, which can only be run with the JRuby runtime:

require 'java'

puts "access java.util.UUID via JRuby"
puts java.util.UUID.randomUUID().toString()
rvm use jruby 
=> Using jruby 1.5.0.RC1

jruby lib/jruby.rb 
=> access java.util.UUID via JRuby
=> a16fda6a-c57d-43b9-8376-801e48fe56b3

The same thing is possible using the Ruby Java Bridge from MRI:

require 'rjb'

puts "access java.util.UUID via RJB"
puts Rjb::import('java.util.UUID').randomUUID().toString()
rvm use 1.8.7
=> Using ruby 1.8.7 p249

ruby lib/rjb.rb 
=> access java.util.UUID via RJB
=> 1db8298c-5486-4933-be00-cdb180388e38

But it is also possible to do it the other way around!

Ruby in Java

Evaluating Ruby code in Java is dead simple with help of the JRuby library. You just need to set up a scripting container that executes your scripts:

  @Test
  public void execute_jruby_scriptlet() {
    new ScriptingContainer().runScriptlet("puts 'hello jruby world'");
  }

A more advanced example is to wire a Ruby class as a Spring bean. You need to provide some configuration and a Java interface that can be used as the basis for the bean:


<lang:jruby id="identifier" script-interfaces="de.nofail.Identifier" script-source="classpath:/ruby/identifier.rb">
    <lang:property name="uuid" value="#{ T(java.util.UUID).randomUUID().toString() }" />
</lang:jruby>
# identifier.rb
class Identifier
  def setUuid(uuid)
    @uuid = uuid
  end
  def getUuid()
    @uuid
  end
  def to_s()
    "Identifier[#{@uuid}]"
  end
end

# don't forget to return an instance as a bean
Identifier.new
// Identifier.java
public interface Identifier {
  String getUuid();
}
// SpringJRubyBeanTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext.xml")
public class SpringJRubyBeanTest {

  @Resource(name = "identifier")
  Identifier identifier;

  @Test
  public void generateUuid_success() {
    System.out.println("uuid: " + identifier);
  }
}

The code is currently not running with JRuby 1.5.0.RC1 so you need the latest stable release for testing.

checking Ruby enginges

It is even possible to mix and match all those approches! You just need to keep track of the Ruby engine that is evaluating your code. I created a little helper called which_ruby (available on rubygems) as a sidekick for this article, but more on that in the next week.

Some Ruby sugar in your cup of Java!

Buildr – The build system that doesn’t suck

If you are a Java guy like me, you are probably doing a lot of ugly tasks in your everday work. One of these tasks is build management.

The Java community tries to tackle builds with standard tools like Ant and “all-in-one” solutions like Maven. Both are based on huge XML configuration files that are hard to read, painful to maintain and impossible to test. Even though these tools are mainstream, they are quite buggy. Just have a look at all the rants about maven you find on the net.

Java builds are known to become very complex over time. You have to compile things found here, include stuff from there, resolve dependencies in a remote repository, add something to the version control, […even more crazy stuff…]. Addressing such complex and dynamic tasks with static structures is just a stupid idea. What you really want to do is scripting!

scripting builds

Using scripting languages is a natural way to address build tasks. If you are close to the operating system you can do most things easily. Trust your admin, the shell is your friend!

The simplest way to get scripting power is to use bash scripts, which has the drawback that it’s not interoperable and you will always have to show consideration for WINDOW$ users…

There are portable frameworks that try to integrate the flexibilty of scripting languages like Ruby with the power of Ant or Maven. Have a look at Gradle, GMaven, Sbt, Raven, Gant or Antwrap as examples.
About one year ago I stumbled over another build tool that claims the slogan The build system that doesn’t suck which I found quite promising!

dynamic builds with Buildr

Buildr is an expressive Ruby DSL for managing builds based on Rake and Ant. Defining a Java project that follows the default Apache directory structure is dead simple:

# buildfile.rb
desc 'define a project called simple'
define 'simple' do
  info 'create a simple.jar from this project'
  package :jar
end

After installing the Buildr Gem you can call built-in or custom Buildr tasks on your project. This is done in the same way Rake would do it:

# install the Buildr gem
gem install buildr

# check buildr version
buildr -V
=> Buildr 1.3.5 (JRuby 1.4.0)

# build your Java project: compile, test, package
buildr package

Since Buildr is based on sensible defaults, it knows where to look for your class files, resources and tests. Before creating the jar, it compiles everything, executes the tests and then zips up the bytecode into a distributable.

Buildr does not support every build feature by default, but it’s easy to extend. Buildr at its core is just a bunch of tasks, chained in a predefined order. You can easily write your own tasks and plug them into the build to fit your needs. Buildr provides method hooks that allow you to integrate your tasks into the build cycle.

If this small example makes you say “Awesome!”, you should have a look at the best documentation of an open source framework I have ever seen. There are some sophisticated examples of how to use Buildr hosted on github as well.

Build, don’t goof up XML!