Skip to end of metadata
Go to start of metadata

I was planning on this issue to be on Camping, but I realized that it would be good to show how to use IRB with JRuby to make life as a Java developer easier. Since Java is a compiled language, it's exceedingly hard to just test things out. My hard drive is completely littered with 5-line programs testing one aspect of the Java libraries or whatnot. If I could have an easy way to interface with the libraries without having to go through a compile cycle, this would ease my life very much. And actually, the last months I have been using JIRB in this way. Of course there is BeanShell and Groovy, but I feel they get in the way. And I'm very fond of IRB, of course.

IRB stands for Interactive Ruby, and JIRB is the name of the program for starting IRB with JRuby. Starting it should be as easy as:

%JRUBY_HOME%\bin\jirb

and after two or three seconds you will get the Ruby prompt:

irb(main):001:0>

At this point, the first thing to do is to require the java libraries, so we can have something to work with:

irb(main):001:0> require 'java'
=> true

I would first like to show how I would go about finding the behaviour of the caret in a Java regexp. (I know I could find it in the API, but this is just to show how you could do it.)

First of all, I will include the relevant class and see what I can do:

irb(main):002:0> include_class 'java.util.regex.Pattern'
=> ["java.util.regex.Pattern"]
irb(main):003:0> Pattern.new
  NameError: wrong # of arguments for constructor
  from D:\Project\jruby-trunk\src\builtin\javasupport.rb:231:in `initialize'
  from (irb):1:in `new'
  from (irb):1:in `binding'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:150:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `signal_status'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:189:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `each_top_level_statement'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `loop'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `catch'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `start'
  from D:\project\jruby-trunk\bin\jirb:13:in `catch'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:71:in `start'
  from D:\project\jruby-trunk\bin\jirb:13
irb(main):004:0> Pattern.methods
=> ["matches", "quote", "compile", "setup_constants", "setup", "singleton_class", "setup_attributes", "new_instance_for", "[]", "const_missing" ...]
irb(main):005:0> Pattern.methods.grep /compile/
=> ["compile"]

Ok, first I include the class, then I try it out. Whoopsie, there was no empty constructor for Pattern. I'm don't really remember what methods are in there, though, so I check out which methods Pattern have. There is a good many of them (and I haven't written them all out either), so I try again by grepping for a method name I believe is in there. Once I've found the method I'm looking for, I call it with the pattern I want to compile, and inspect the result in various ways. I vaguely remember a matcher method, and it seems to work as I remember:

irb(main):008:0> pt = Pattern.compile("^foo")
=> ^foo
irb(main):009:0> pt.inspect
=> "^foo"
irb(main):010:0> pt.java_class
=> java.util.regex.Pattern
irb(main):011:0> pt.class
=> Pattern
irb(main):012:0> m = pt.matcher("foo")
=> java.util.regex.Matcher[pattern=^foo region=0,3 lastmatch=]

Ok, now I have something to work with. Good, and the standard output from JRuby gives me some insight into the internals of the matcher too; interesting stuff. There is a find method, and a matches method on the Matcher:

irb(main):013:0> m.find
=> true
irb(main):014:0> m.find
=> false
irb(main):015:0> m.matches
=> true
irb(main):016:0> m.search
  NoMethodError: undefined method `search' for java.util.regex.Matcher[pattern=^foo region=0,3 lastmatch=foo]:#
  from (irb):1:in `method_missing'
  from (irb):1:in `binding'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:150:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `signal_status'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:189:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `each_top_level_statement'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `loop'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `catch'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:190:in `eval_input'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:70:in `start'
  from D:\project\jruby-trunk\bin\jirb:13:in `catch'
  from D:/project/jruby-trunk/lib/ruby/1.8/irb.rb:71:in `start'
  from D:\project\jruby-trunk\bin\jirb:13

I also belived there was a search method, and also a way to get back to the initial state of the Matcher. Hmm. Time to check out the methods of this object too:

irb(main):017:0> m.methods
=> ["hashCode", "start", "matches", "useAnchoringBounds", "region", "reset"...] irb(main):019:0> m.reset
=> java.util.regex.Matcher[pattern=^foo region=0,3 lastmatch=]
irb(main):020:0> m.find
=> true
irb(main):021:0> m.group 0
=> "foo"
irb(main):022:0>

I found the method I was looking for; reset, calls it and tries find again, and then gets the group with index 0, which is the complete match.

Some Swinging

JIRB works great for trying out Swing interactively. I'm just going to show a tidbit of this, and since this is one of the more common examples of JRuby, you will be able to find many different demonstrations of this on the net.

We first require java-support, and including the required classes for this example:

irb(main):001:0> require 'java'
=> true
irb(main):002:0> include_class(['javax.swing.JFrame','javax.swing.JLabel','javax.swing.JButton','javax.swing.JPanel'])
=> ["javax.swing.JFrame", "javax.swing.JLabel", "javax.swing.JButton", "javax.swing.JPanel"]

Then we create a frame and some panels:

irb(main):003:0> frame = JFrame.new("JRuby panel")
=> javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=JRuby panel,resizable,normal,defaultCloseOperation=HI
  DE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,fl
  ags=16777673,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
irb(main):004:0> basePanel = JPanel.new
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
  eferredSize=]
irb(main):005:0> labelPanel = JPanel.new
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
  eferredSize=]
irb(main):006:0> buttonPanel = JPanel.new
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
  eferredSize=]

After this, we add some labels and some buttons to the panes, and then add the panes to the base pane, and the base pane to the frame.

irb(main):007:0> labelPanel.add JLabel.new("Isn't JRuby cool?")
=> javax.swing.JLabel[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultI
 con=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Isn't JRuby cool?,verticalAlignm
 ent=CENTER,verticalTextPosition=CENTER]
irb(main):008:0> labelPanel.add JLabel.new("JIrb is very useful")
=> javax.swing.JLabel[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultI
 con=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=JIrb is very useful,verticalAlig
 nment=CENTER,verticalTextPosition=CENTER]
irb(main):009:0> buttonPanel.add JButton.new("Pushbutton without action")
=> javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@1354
 355,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIReso
 urce[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=
 ,selectedIcon=,text=Pushbutton without action,defaultCapable=true]
irb(main):010:0> basePanel.add labelPanel
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
 eferredSize=]
irb(main):011:0> basePanel.add buttonPanel
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
 eferredSize=]
irb(main):012:0> frame.add basePanel
=> javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,pr
 eferredSize=]

Then it's just to pack the contents and show the frame:

irb(main):013:0> frame.pack
=> nil
irb(main):014:0> frame.show
=> nil

To continue playing the Swing, just poke away at the methods. You can always change it if something goes wrong. After you're finished you can dump most of the structure very easy. Just remember to call show again to see some of the updates. Certain changes call redraw directly, but mostly it's always a good choice to call show after updates on the structures.

  • No labels

1 Comment

  1. The console is very cool! I just could not find that I need to hit TAB for auto-completion on this site. Some explanations for the console would be appreciated.