Skip to content
Print

Rapid Prototyping with JRuby

16
Feb
2007

For this entry, let’s consider a situation which arises fairly frequently in real world development: the need to quickly prototype something. Now, when I say prototype, I mean something even more atomic than building a demo of an application or feature. What I’m talking about is trying out a certain aspect of an API to make sure it works as expected; or possibly something even more trivial like quickly retrieving a system property.

Now, Java as a language just doesn’t lend itself very well to this kind of development. I’ve heard it said that “in a world of lightweight tools, Java is a sledge-hammer.” While this analogy is somewhat derogatory, it’s true to a certain extent. The way the Java language is structured syntactically, coupled with the sheer overly-designed bulkiness of most Java APIs, makes Java utterly unsuitable for quickly trying something with a minimum of fuss. For example:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
 
import javax.swing.JComponent;
import javax.swing.JFrame;
 
/*
 * Created: Feb 16, 2007
 */
 
/**
 * TODO	add description
 *
 * @author Daniel Spiewak
 */
public class TestClass {
    public static void main(String... args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                final GradientPaint paint = new GradientPaint(0, 0, Color.BLACK, 0, 200, Color.WHITE);
 
                JFrame frame = new JFrame("Test Frame");
                frame.setSize(200, 200);
 
                JComponent component = new JComponent() {
                    @Override
                    protected void paintComponent(Graphics g) {
                        Graphics2D g2 = (Graphics2D) g;
 
                        g2.setPaint(paint);
                        g2.fillRect(0, 0, getWidth(), getHeight());
                    }
                };
                frame.getContentPane().add(component);
 
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

This example could be code produced by someone trying to test the Swing gradient functionality. Here, however, is the corresponding JRuby code:

require 'java'
 
JFrame = javax.swing.JFrame
JComponent = javax.swing.JComponent
GradientPaint = java.awt.GradientPaint
Color = java.awt.Color
 
class CustomComponent < JComponent
    @paint = GradientPaint.new(0, 0, Color::BLACK, 0, 200, Color::WHITE)
 
    def initialize
    end
 
    def paintComponent(g)
        g.paint = @paint
        g.fillRect(0, 0, getWidth, getHeight)
    end
end
 
frame = JFrame.new 'Test Frame'
frame.setSize(200, 200)
 
frame.add CustomComponent.new
 
frame.defaultCloseOperation = JFrame::EXIT_ON_CLOSE
frame.visible = true

There, isn’t that ever so much cleaner? :-) (actually, readers who haven’t fallen asleep yet will notice I cheated in the JRuby version by not wrapping everything into the EDT, but that’s another post…) Either way, the result is the same (pictured right), a simple JFrame showing a full gradient from black to white. Not a terribly impressive example, but one which does demonstrate the atomic nature of a lot of modern prototyping needs. But let’s look at something smaller for a moment…

Let’s say that you’re building some code which needs to (among other things) detect the exact operating system upon which it is running and perform different operations based on those facts. This is a fairly common scenario among desktop applications. In fact, I came across it myself just a few days ago. Now, Java provides a system property which returns a string representation of the operating system name. (it’s the os.name property) While this is a good starting place, the property itself doesn’t follow a standardized format. And since the only way to really determine the OS name is to perform string manipulation on the value – which is in a non-standardized format – we’re a bit up the creek.

The only way to be sure we’re running our tests properly is to actually examine the value of the os.name property. This would be ever-so-easy if Java provided a nice mechanism to peer into the standardized system properties, but alas, no such mechanism exists. The only way to get a property value, in fact, is to actually run some code which retrieves the value and prints it out. Unfortunately, due to Java’s rather verbose syntax, such a program would be ridiculously long (given the problem). A better way is to use the JIRB utility, an interactive JRuby console:

Microsoft Windows [Version 6.0.6000]
Copyright (c) 2006 Microsoft Corporation.  All rights reserved.

C:\\Users\\Daniel Spiewak>jirb
irb(main):001:0> require 'java'
=> true
irb(main):002:0> System = java.lang.System
=> System
irb(main):003:0> System.getProperty 'os.name'
=> "Windows Vista"
irb(main):004:0> exit

C:\\Users\\Daniel Spiewak>

And it’s just that simple. In fact, I have JRuby installed on all of my test systems for precisely this reason. It’s so easy to do really quick, highly atomic prototyping in JRuby. Things (such as the OS name example) which would ordinarily take five to ten minutes of typing (in Java) require mere seconds in JIRB.

Comments

  1. Interesting post – thanks!

    Vasudev Ram
    http://www.dancingbison.com

    Vasudev Ram Sunday, February 18, 2007 at 8:53 am
  2. Very useful.. it is so hard to find JRuby examples at the moment, crazy as this project has so much potential.

    Worth noting that this demo requires the SVN version of JRuby .. or at least something much newer than 0.9.2.

    Thanks, T.

    Tom Thursday, March 1, 2007 at 5:34 am
  3. @Tom

    Yeah, I think this was the demo I cheated on and didn’t bother testing the JRuby code. :-) It is also possible that I did test it, but against the SVN version. I try to keep my demos 0.9.2 compatible, but… *shrug* :-)

    Daniel Spiewak Thursday, March 1, 2007 at 10:45 am
  4. Interesting…

    Vangelis Friday, September 14, 2007 at 10:22 pm
  5. Thanks for posting… good stuff. Jruby is at the top of my learning list…

    Ron Sweeney Saturday, November 17, 2007 at 7:47 pm
  6. Thanks for posting. Examples like this are nice when learning jruby. Jruby looks very nice for prototyping, and programming in science projects.

    I had to move the instance variable @paint into def initialize to get it working in jruby 1.0.3 (java 1.6.0_03 ubuntu)

    def initialize
    @paint2 = GradientPaint.new(0, 0, Color::BLACK, 0, 200, Color::WHITE)
    end

    Tomasz Wednesday, January 2, 2008 at 8:36 am
  7. So, perhaps you can help, but one thing that none of the examples im finding shows is how to run an application written in java from JRuby. Actually trying to run MagicDraw (www.magicdraw.com) from JIRB so that I can use the MagicDraw OpenAPI directly to manipulate models and have a chance to try out the MagicDraw OpenAPI on a specific project model before putting the code into eclipse to compile a java plugin…. Any thoughts? Im able to get all the jars included and can then do the import_class for the Main class which is used for launching the program. But after this it crashes with complaints and im afraid its just a shortcoming of me not know what i need to be doing from the jruby side of things….

    Matt Tuesday, September 21, 2010 at 11:18 am

Post a Comment

Comments are automatically formatted. Markup are either stripped or will cause large blocks of text to be eaten, depending on the phase of the moon. Code snippets should be wrapped in <pre>...</pre> tags. Indentation within pre tags will be preserved, and most instances of "<" and ">" will work without a problem.

Please note that first-time commenters are moderated, so don't panic if your comment doesn't appear immediately.

*
*