Jun 14 2007

Ruby / Oracle / Mac OS X pain - JRuby and ActiveRecord JDBC to the rescue!

Julian Doherty

A while back I wrote about my frustrations trying to get Ruby to talk to Oracle on Mac OS X. I’ve tried a new approach using JRuby and ActiveRecord-JDBC with great success.

What I’m after is quite simple: I just want to use Ruby for some simple housekeeping scripting tasks which occasionally means connecting to Oracle to shunt data around. So this is all outside of Rails, which adds to the fun.

The basic problem with Oracle on Mac OS X is that Oracle support is lousy (add that to my list of complaints :P). There is no standard client install, hence no standard Oracle C libraries. While there is a stripped down version of the libraries - it is only available compiled for PowerPC. So no go with Intel CPUs (unless you want to recompile Ruby for PowerPC and run in emulation mode - just to allow you to build the OCI adapter. yech)

So I gave up.

Until I gave it another shot with JRuby and ActiveRecord-JDBC. Here’s a quick guide:

Install gems

From the command line:

gem install activerecord

gem install ActiveRecord-JDBC

A trap for new players is to make sure you’re using JRuby gem utility, and not the Ruby one - tripped me up.

Setup DB

This can be whatever you’ve already got, or maybe a new DB. Here’s what I’m using for this example:

--our table to test the setup.
--note standard activerecord setup with 'ID' as primary key
create table TEST_MESSAGES
(
  ID      NUMBER not null,
  MESSAGE VARCHAR2(100)
);
alter table TEST_MESSAGES
  add constraint test_messages_pk primary key (ID);

--sequence used to populate PK
create sequence test_messages_seq;

Setup your classpath

Make sure you’ve got your Oracle JDBC driver in a handy directory, and run export CLASSPATH=ojdbc14.jar from your favourite command prompt. You can get the ojdbc14.jar driver file from Oracle’s JDBC download page, although in general I find Oracle’s site on a par with trying to Find Permit A-38 in terms of frustration…

Run some Ruby code against it

Now for the fun bit.

# active_record is the standard rails AR require
require 'active_record'

# jdbc_adapter is in ActiveRecord-JDBC, and makes a JDBC adapter 
# available to ActiveRecord
require 'active_record/connection_adapters/jdbc_adapter'

# Connect to the database 
# - this is required because we're running without rails.
ActiveRecord::Base.establish_connection(:adapter  => 'jdbc',
                                        :driver   => 'oracle.jdbc.driver.OracleDriver',
                                        :url      => 'jdbc:oracle:thin:@server:1521:database',
                                        :username =>  'username',
                                        :password =>  'password')

# our model class that maps to the table we created
class TestMessage < ActiveRecord::Base
end

# insert a record                                
hi_message = TestMessage.new
hi_message.message= 'Hello World!'
hi_message.save

# and another one for fun
ar_message = TestMessage.new
ar_message.message = 'This is activerecord JDBC on Oracle'
ar_message.save

# should spit back out both our inserted records
TestMessage.find(:all).each do |m|
  puts m.message
end

In this example I used ActiveRecord standard table structures, but in practice I was connecting to legacy databases. ActiveRecord is still quite useful with legacy databases, but you just have to do a bit more setup. set_primary_key and set_table_name will get you some of the way. has_many and belongs_to with the :foreign_key option will get you most of the rest of the way.


Jun 7 2007

Ruby vs JRuby Fractal Benchmark

Julian Doherty

After reading about benchmarking various languages generating fractal patterns, I tried throwing the Ruby code at both the standard MRI Ruby and JRuby interpreters to compare relative performance. This is all totally unscientific, but is interesting all the same.

MRI Ruby (Matz Ruby Interpreter)


ruby 1.8.5 (2006-12-25 patchlevel 12) [i686-darwin8.8.1]

Rendering

Ruby Elapsed 6.732136

JRuby


ruby 1.8.5 (2007-06-04 rev 3812) [i386-jruby1.0.0RC3]

Rendering

Ruby Elapsed 68.757000

C Ruby is the clear winner, but that’s not so surprising. What is surprising is how far JRuby was behind - by at least 10 times. I’ve heard good things about JRuby’s ability to compile Ruby down to bytecode, but I didn’t have too much luck with that. Admittedly I didn’t play around with it for long.

I was curious where the bottlenecks are in both versions. After running the code through both VMs with the -r profile flag, really slow floating point operations turned out to be the culprit. The profile for each was pretty much identical. Lots of float operations (+ / < * etc), with everything multiplied by 10 for the JRuby VM.

So what does this tell us? Pretty much nothing. Most apps won’t be doing this kind of CPU heavy crunching (and if you’re using an interpreted language you’re asking for trouble). Especially the kind of apps you’d use either MRI Ruby or JRuby for, which spend most of their time waiting for the database. I might have another play and see if I can get JRuby to run using bytecode - the hype is that it will be as fast if not faster than MRI.

Disclaimer - I’m actually a huge fan of both MRI Ruby and JRuby and just did this out of curiosity. Put AWAY the flame torches now…

Update - JRuby can actually be as fast or faster than MRI

Charles Oliver Nutter (of the JRuby team), has added some suggestions for tuning the JRuby VM. The following is also in the comments, but I’ve included it in the main post as it is useful information that might get missed. What is really interesting is that JRuby is faster in this case when the VM is tuned and the code gets a chance to run enough for the JIT compiler to kick in.

FYI, I grabbed the code in question to try it out myself. These are my numbers using JRuby trunk (not really different from RC3), Java 6 server VM on OS X, and the following command line:

jruby -J-server -J-Djruby.jit.threshold=0 -O fractal.rb

JRuby:

Ruby Elapsed 6.454000

Ruby 1.8.6:

Ruby Elapsed 6.971203

The command line above adds three options:

-J-server turns on the server VM

-J-Djruby.jit.threshold=0 sets the JIT threshold to zero, so it will try to compile methods immediately (critically important for this benchmark since the methods are only called once), and -O turns off ObjectSpace, which is pure overhead for us.

Additionally, if I let the benchmark run ten times, allowing the JVM to optimize it further, I get the following result for JRuby on the tenth iteration:

Ruby Elapsed 5.629000

There’s a good page in the JRuby Wiki for performance tuning JRuby. The reason this wasn’t compiling is twofold: the methods weren’t called enough times to trigger the JIT, and the script itself had a “class” definition in it, which the compiler doesn’t yet handle.

Cheers Charles, extremely useful.


Mar 9 2007

JRuby can save Swing - Follow up

Julian Doherty

My recent post "JRuby Can Save Swing" generated a bit of discussion around the blogosphere. A few blogs replied, and a lot of good points were made. I was a little disappointed that most of the rebuttal I got was in regard to Joshua Marinachi’s original 2003 post and his list of why Swing sucks, and not to the points I raised about the potential that a new framework based in JRuby could provide. I guess that is blogging-101 - put your payload at the front and minimize the lead up. ;)

From the original post, my dream list for a higher level GUI framework for Swing are

  • Structured application layout
  • Proper decoupling of model from view
  • Automatic binding of model to view without glue code
  • View logic code separated from layout markup
  • Application lifecycle support
  • Minimize the amount of code
  • Minimize complexity
  • Testable
  • Make the Right way of doing things the path of least resistance

JRuby cannot save Swing

pinderkent replied with the idea that Swing is beyond saving, and nothing JRuby or anything else can do can save it. I don’t think Swing is at that point. I think in the last few years Swing has turned a corner an is improving with each release (5 was great, 6 is good as well). My initial article title was intentionally a little inflammatory. I don’t actually think Swing “needs” saving. All the same I think there are some areas that can be helped out.

Swing is slow?

Pinderkent then trots out the tired “Swing is slow argument”. This may have been the case… on a Pentium 2 back in 1998. This has not been true for a long time. Swing itself is more efficient, and CPUs are faster. It just isn’t an issue anymore. The pinderkent says they haven’t actually done any profiling. Nuff said.

Danno Ferrin responded to pinderkent and makes the point in another follow up:

"The stock answer to this is always true: "bad programmers abuse the Event Dispatch Thread." Seriously, whenever anyone wants to start programming Swing someone else needs to get a stick and beat them until they write in blood the oath "I will not do data processing in the Event Dispatch Thread." "

Which is exactly my experience. It is possible to create snappy, responsive Swing apps - but the moment anyone does some heavy processing, or a database call, or file operation from a listener - you’re wading through mud. Maybe that’s an extra point for my framework wish list: "Makes using worker threads instead of the EDT the path of least resistance for heavy operations."

Groovy Can Save Swing

Danno Ferrin’s main point is that Groovy would be a more suitable layer for Swing than JRuby.

The argument is that Groovy is closer to Java and it would mean developers wouldn’t have to learn all of Ruby’s weird syntax and "ugly PERLisms". Maybe. I have to admit I haven’t had any exposure to Groovy. Ruby isn’t difficult to pick up though, and the syntax arguments are really just a matter of opinion. What I believe makes Ruby ideal as a DSL/wrapper API layer is the level of meta-programming Ruby affords to achieve things that are impossible in Java. I’m talking about things like stupidly easy model-view binding. In ruby you can do something like

model = Person.new('Julian Doherty', 'julian@example.com')

name_label = JLabel.new
name_label.bind_to model, :name

email_field = JTextField.new
email_field.bind_to model, :email

And have the text label and field bound to the model so changes on either side are automatically replicated to each other - all without a single line of event listener glue code. I’ve got some sample code showing this working, and will write something about it soonish. I’ve already written about Transparent Property Change Listeners for Ruby bean-type classes, which shows part of the solution.

I don’t know if Groovy gives you that or not. If it does, great. If not, then that’s a reason to consider JRuby over Groovy.

Homework for me: grok Groovy so I’m better informed on this :)

Does Swing Need Saving?

Daniel Spiewak posted a rebuttal of Joshua Marinachi’s original “why Swing Sucks posts” that I reposted.

It’s a good post and A lot of his points were on the money (which I won’t discuss much except to say I agree): his discussion of layout managers (GroupLayout etc); native feature integration; and Swing’s bad perception from a troubled past.

A few didn’t quite stack up with me though.

Ruby is the same amount of work as Java?

In arguing that Swing GUIs are just as easy to construct in Java as JRuby, Daniel Spiewak provides an overly simple UI consisting of a label and three buttons - implemented both in JRuby and then Java. The two versions are almost identical, and there is no difference in code complexity or length (how surprising!). Problem is, the examples didn’t have anything done in the real world: no advanced layout, no event handling, no model/view interaction, no validation. It’s a weak straw man argument that really doesn’t tell us anything.

A more interesting example would be to compare a straight Java implementation of a reasonably complex application (including any cool 3rd party libraries) and a JRuby framework based implementation (using all the Ruby black magic possible). My guess is that the JRuby version would come out ahead.

Swing isn’t slow to build?

Daniel Spiewak then says that a reasonably complex UI could be coded in a few hours by a himself, and half that by Romain Guy.

So what?

It’s a pretty arbitrary metric which still doesn’t say anything. What would be interesting again is the difference between Java and a JRuby framework implementation. Maybe JRuby only takes one hour or maybe it takes five? I don’t know. My guess though is that again it would take far less code, would be easier to test, and would be finished quicker in JRuby by the same developer.

Separate markup layout of view is bad?

Daniel Spiewak also questioned whether using XML to store the GUI config is a good idea. I AGREE! XML is horrible and is abused in Java land (I actually said to use YAML in the original post as it is a bit more human friendly). I wasn’t advocating to use XML/YAML to create the whole GUI - just as a mark up to separate the layout from the component instantiation and move layout out of the view code.

My opinion is that code is good for expressing view logic, but not visual layout. That would be better served by some separate markup.

Swing apps are hard to maintain because of bad developers?

One of the main beefs I’ve got with Java/Swing and one that Daniel Spiewak’s touched on, is the difficulty maintainability of Swing apps. He says that main problem with bad Swing apps is that bad developers don’t do a good job - which I totally agree with! It is definitely possible to structure a good Swing app and develop it in a nice clean way, but to do things the right way is a lot of work. The path of least resistance is to take short cuts and just get it done (especially when deadlines are pressing). Yes, Swing has a nice MVC architecture, and best practice says you should build apps that way - but it’s just too much work to use properly in the real world.

I liked a quote from one of Danno Ferrin’s other related blog posts “Groovy, Verbosity, and Swing:

“I think that the greatest problem with the swing APIs are not that they are too complex or too poorly explained. The biggest problem I see is that to do simple things the correct way, it can get quite verbose. Kind of like reliable file I/O, but you get far fewer urgent-1 bug in the GUI than in core I/O routines. Perhaps the best thing isn’t to change the Swing APIs, but to add more syntactic sugar.”

Which is exactly what I was trying to get at with my original post. Swing is a great low level API, and provides the developer with a lot of power to do things. Problem is, the path of least resistance is to produce ugly crud that barely works. Where as something like Rails provides a path of least resistance that results in elegant and well structured code.

Every API acts like a multiplier for developer productivity, and has a response curve of varying slope. Some frameworks make good developers amazing while making mediocre developers passable (Rails springs to mind).

Swing seems to do the opposite though. It makes amazing developer’s work merely good, and mediocre developer’s work unacceptable.

Comments on the original post

Why not Eclipse/NetBeans RCP? What about JSR-296 application framework?

Steve said…

I agree with the sentiment, but not to craft yet another solution.

Why don’t we just call this Eclipse or NetBeans RCP?

Really these things have been done, what we lack is people understanding and using them.

There is a JSR on the table for a Swing framework too - JSR-296, this will help quite a bit.

Good points. I have to plead ignorance on exactly what the Eclipse and NetBeans RCPs provide (more homework for me!). However one of the benefits of JRuby is all the meta-programming that is either impossible or overly verbose in Java. They also both smack of the whole Big Java philosophy (XML configuration and all!) which a lot of developers are getting disillusioned with. As for JSR-296 - it’s definitely a good thing, and any framework should build on top of it, not replace it.

Groovy SwingBuilder?

Anonymous said…

Groovy already has a SwingBuilder, which I suppose you could duplicate in Ruby… but most of these are done arleady.

Good point, but layout is just a small piece of the puzzle. My understanding is that SwingBuilder just helps you with the layout and still leaves everything else (binding, application structure etc) to you to implement

So… now what?

I’m keen to experiment with some of my original ideas from JRuby Can Save Swing. I’m trying to pick a small/medium, low-risk project to roll a basic JRuby Swing framework for and see how it goes. So far I’ve been doing a few little demos that show off some of the basic concepts (will post some examples soon!). It’s definitely promising, but it’s hard to tell from anything that small.

Stay tuned :)


Mar 7 2007

JRuby 0.9.8 Released

Julian Doherty

JRuby 0.9.8 is out. I’ll have to download and give it a blast in the next day or two. I’ve got some more JRuby code snippets to post, so will be interesting to see how it runs.

Looks like it’s got some nice performance and Java integration improvements. AND 98% of Rails unit tests pass. This is the release they consider to be stable enough for Rails developers to start playing with seriously to help the JRuby team get over the line.

Release is available at http://dist.codehaus.org/jruby/


Feb 15 2007

JRuby can save Swing

Julian Doherty

Swing is hard. Needlessly so. With the advent of scripting support on the JVM, why not wrap a light and elegant Ruby layer around Swing? Why keep coding Swing at it’s lowest API level using a heavy-weight language like Java?

I’ve always maintained Swing is a nice framework. It’s just that it’s too low level and Java is a lousy language for programming it in. It’s already possible to code Swing in Ruby by using JRuby. You get some of the Ruby niceness (such as easier method calls, some dynamic typing, and blocks), but you still end up fighting against listeners, layout managers, look-and-feels, event-threads etc before long. Suns trademark API over-engineering casts a long shadow, even into Ruby land.

The Swing API itself is very flexible and powerful, but at a low level. It’s powerful in the same way that a coil of wire and a bunch of tools is a flexible and powerful way to configure the electricals in your house. It’s just that sometimes you only want to plug a few things in and flick a switch to watch a DVD.

So what specifically are the problems?

Swing’s issues

Joshua Marinacci’s blog post Swing has failed. What can we do? from 2003 covers this issue nicely. Joshua points out these flaws which I’d agree with 100%. Nothing much has changed in the years since, except maybe that Swing looks somewhat better now and resembles native apps much more closely.

  • "Swing apps are slow to build."
  • "Swing layout managers suck."
  • "Swing apps are hard to maintain."
  • "Swing is too powerful."
  • "No native features."
  • "Swing apps have a bad history."

What needs to be done?

Joshua’s ideas on what needs to be done to fix Swing are interesting.

(there are more points he makes, but I’m just including the relevant ones)

  • "A structured way of building Swing apps. Something like Struts where each concern (aspect?) has it’s own special place to be stored and manipulated. How do you organize your layout, workflow, validation, intz’ed text, and hooks to the BL? Should you subclass to make frames or use factory code? We need a set of best practices and then a framework to implement them."
  • "A standard cross-tool representation of a GUI that is not Java code. Something that can be moved in and out of different IDEs and build tools. Probably an XML representation or maybe serialized Swing objects."
  • "An intermediate API. Maybe we need a simpler API on top of Swing? A new set of wrapper components which hide a lot of the complexity. Hell, half of the work could be done by just conditionally hiding 3/4 of the API from the Javadocs."

I particularly like the idea of a structured way of building Swing apps. At the moment it’s a free-for-all. Some developers have come up with nice individual patterns for maintaining order, others implement spaghetti, most start out well, but degrade into entropy. This even applies individual screens in some apps! - I’ve seen 6000 line long, single-class monstrosities for a single window! One of Rails main strengths is it’s “Convention over Configuration” approach for separating out and structuring an application. There is no reason why this can’t apply to a Rich Client.

My Ideal Swing/Ruby framework features

So… what would this look like?

  • Structured application layout. Works for Rails. Nuff said.
  • Proper decoupling of model from view. Probably using Martin Fowler’s Presentation Model pattern, or similar.
  • Automatic binding of model to view without glue code. (this makes the last point much easier to implement.) Ruby is perfect for this. You should be able to write something like name_field.bind_to song, :title and be done with it. Ruby should do it’s thing and set up listeners automatically - Even if the model class wasn’t designed with listeners when it was coded.
  • View logic code separated from layout markup. View components and interaction (enable this button with this tooltip etc) should be coded in Ruby. Layout should be stored in a YAML file or similar (please no more XML…). Layout via coding is far too hard for most people to use effectively. Minimize the pain and let the framework take care of the grunt work. We definitely DO NOT want anymore GridBag boilerplate code…
  • Application lifecycle support. Related to having a structured application layout. Provide session support, long lived models etc, and handle startup/shutdown.
  • Minimize the amount of code. You already get this for free by using Ruby, but removing the fluff from Swing is a must. Too much code to achieve too little. It should be possible to scaffold something basic like Rails does, then tweak it if it needs to do more. DRY is part of this, but that just seems like basic common sense for any kind of development in any language.
  • Minimize complexity. Related to minimizing code. Making it easy to use a proper pattern like Presentation Model and removing a lot of the spaghetti listener code by using bindings will help a lot.
  • Testable. It’s really hard to write automated tests for GUIs. Libraries like JFC Unit make it easier, but it’s still pretty heavy going. I don’t know the answer to this one. GUIs always need at least some manual intervention to check the visual layout (a computer can’t tell if it doesn’t “flow” right). Maybe the framework could help by making it easy to substitue mock objects for testing the presentation model code.
  • Make the Right way of doing things the path of least resistance.. This one is important, and I think it is one of Swing’s big weaknesses. This is related to having a good structure, but it goes from there all the way down to how easy the APIs are to use. Rails makes it easy to create good designs and stick to them. Swing makes it hard - as evidenced by the plague of badly thought out Autonomous Views espoused by Sun’s Swing tutorials

Even a few of these points would make Swing much more productive and fun. I’ve made a few posts recently that are leading up to this. Over the next few posts I’ll start to experiment with a few more of the pieces to see how it all hangs together. Who knows, maybe I’ll actually get something usable at the end :)


Jan 25 2007

Java style stacktrace for JRuby code called from Java

Julian Doherty

As part of a project to write some nice Ruby APIs for creating Swing GUIs, I’ve been a little frustrated with the exceptions from JRuby in the Java code that calls it - particularly getting stack traces, and error messages.

Say you’ve got some code like this:

try {
  new ScriptEngineManager().
      getEngineByName("jruby").
      eval("raise 'foo is too bar'");
} catch (Exception e) {
  e.printStackTrace();
}

You’ll get output that looks something like:

javax.script.ScriptException: org.jruby.exceptions.RaiseException
  at com.sun.script.jruby.JRubyScriptEngine.evalNode(JRubyScriptEngine.java:376)
  at com.sun.script.jruby.JRubyScriptEngine.eval(JRubyScriptEngine.java:138)
  at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:245)
  at Borked.main(Borked.java:9)
Caused by: org.jruby.exceptions.RaiseException

Not very helpful. How are you supposed to know what went wrong where?

After a bit of poking round with the debugger, it turns out there is more information in the exception you get back. You just have to work to get it. The following code will grab the Ruby exception message and stacktrace and spit it back out in the same style as native Java exceptions are output.

try {
  new ScriptEngineManager().
      getEngineByName("jruby").
      eval("raise 'foo is too bar'");
} catch (Exception e) {
  RaiseException re = (RaiseException)e.getCause();
  System.out.println(re.getException().getMetaClass() + ":" + re.getException().toString());
  RubyArray rubyStackTrace = (RubyArray) re.getException().backtrace();
  for(Object stackLine : rubyStackTrace) {
    System.out.println("\tat " + stackLine);
  }
}

Here’s the output from some code I’ve been working on

ArgumentError:unknown key:foo
  at /development/wring/classes/wrung_test.rb:17:in `each'
  at /development/wring/classes/wrung.rb:43:in `populate_defaults'
  at /development/wring/classes/wrung_test.rb:17:in `add_comp'
  at /development/wring/classes/wrung_test.rb:17
  at :0:in `require'
  at :0

Which is pretty much exactly what a Java stack trace would look like - except its for the Ruby code running inside JRuby called by Java.