Sat
1
Apr '06
Errorhandling Ruby vs. Java
by Frank Spychalski filed under articles, Rants, Computer, Ruby

If you find this useful, you might like my other articles, too.

At my daytime job I had to rewrite a class which sends a Message to a Queue. Sounds simple? With EJB3 it is reasonably simple and can be done in around 10 lines of code involving lots of lookups. But if you are looking for a reliable solution which works even when the application server reboots every once in a while your code gets messy. My current solution has 120 lines of code and there are still some things to add like buffering of unsent messages.

Bloated Exceptionhandling

Why do I have to write so much more code to get a reliable solution? Part of the blame is on Java, because of its verbose exception handling - there is no elegant way of catching 2 or more exceptions[1] without catching Exception or Throwable, which I try to avoid where possible. Ruby has this simple solution compared to the bloated solution in java, especially with EJB where you have to catch half a dozend different exceptions.

begin
  eval string
rescue SyntaxError, NameError => boom
  print "String doesn't compile: " + boom
rescue StandardError => bang
  print "Error running script: " + bang
end
Retry

Repeating whole blocks of code needs too much code, too. Ruby has the retry command, which restarts the current block:

c = 0
for i in 1..100
  tries = 0
  begin
    c = c + 1                 # dummy code
    if c % 4 != 0             # to create
      puts "failed for #{i}"  # a few
      raise "uups"            # exceptions
    end
    puts "action #{i}"
  rescue
    puts "rescue"
    tries = tries + 1
    retry if tries < 3
  end
end

This is just another name for goto, which might be harmful. Actually, I wouldn’t use this solution anyway because there is a better, more reusable way, to achieve the same.

closures

In ruby, it is possible (and very simple) to pass some code to a method. This allows me to create a method which excecutes my code multiple times, if an exceptions occurs:

def try(max_tries = 3)
  tries = 0
  begin
    yield
  rescue
    puts "rescue"
    tries = tries + 1
    retry if tries < max_tries
  end
end

c = 0
for i in 1..100
  try do
    c = c + 1                 # dummy code
    if c % 4 != 0             # to create
      puts "failed for #{i}"  # a few
      raise "uups"            # exceptions
    end
    puts "action #{i}"
  end
end

When I started this article, I just wanted to write a short rant about the missing features for errorhandling in java. While writing, I noticed that Ruby has them. Perhaps that’s the reason why I enjoy programming in ruby so much :-)

[1]to clarify this point just for Jason: In general, there is no elegant way of catching two or more exceptions. If you look at the number of direct subclasses in java.lang.Exception, it is nearly impossible to catch the exceptions you want using a superclass without catching some ‘innocent bystanders’.
I would very much like to see a elegant solution which catches only java.sql.SQLException and java.util.concurrent.TimeoutException, you may use as much OOP and polymorphism as you like. This might not be the fault of the language but the plattform but as I cannot get one without the other, it doesn’t really matter to me. Don’t get me wrong, I think Java is pretty damn good, but there is still a lot of room to improve. And Ruby is showing some of the things which can be done better.


9 Responses to “Errorhandling Ruby vs. Java”

  1. 1

    What are you using as a Queue in Ruby? I am looking for a good message que to use with ruby. Something really robust and fast.

    mal (April 1st, 2006 at 11:49)
  2. 2

    The queue I was refering to, was a Java JMS Queue within JBoss. For what do you need a queue and what kind of problem are you trying to solve with it?

    Frank Spychalski (April 1st, 2006 at 12:56)
  3. 3

    Everyone who is intrested digging deeper into Rubys error handling and it’s pros and cons and philosophical motivations behind it, should read the following paper (now online). Like many other things, Common Lisp has the most advanced condition system in existence. Ruby’s is restricted version of that.

    Condition Handling in the Lisp Language Family
    http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html

    This paper appears in Advances in Exception Handling Techniques,
    edited by A. Romanovsky, C. Dony, J.L. Knudsen, and A. Tripathi.
    This book, published in 2001, is part of Lecture Notes in Computer Science, Volume 2022,
    published by Springer.

    notany (April 1st, 2006 at 16:21)
  4. 4

    Two queue ideas for Ruby.. Spread is a good messaging system that’s been around years and there’s a good Ruby client library. Just been playing with it, very nice. Alternatively, BerkeleyDB has a Queue mechanism. Both of these are mature technologies.

    Peter Cooper (April 1st, 2006 at 19:42)
  5. 5

    notany, Peter: thanks for the pointers

    Frank Spychalski (April 1st, 2006 at 20:25)
  6. 6

    This article is written very poorly. You need to supply an example that compares and contrasts java code vs. the ruby code. Maybe code the same solution in both languages. As far as your comment ” there is no elegant way of catching 2 or more exceptions without catching Exception or Throwable” is concerned, you are wrong. You need to look into OOP and polymorphism. Also, look at some design pattern books, then maybe you can start posting comments why you think ruby is so much better than java. ps, your site breaks in the Opera browser.

    Jason (April 1st, 2006 at 21:55)
  7. 7

    Hello Frank,

    exception handling in Java is one of the thing most people do complain about because it bloats the code. Well, yes, my opinion is that it is (done the Java way) one of the most powerful features other languages do lack.

    Though languages like PHP5 or Ruby have exception handling nowadays, it is only kind of “Runtime”-exception handling, you do not have to catch exceptions explicitly. This is the same in Delphi or .NET, as far as I know. This strips of much code and sppeds development.

    But on the other side, in every language you have to do have to code more and more, “if you are looking for a reliable solution which works even when …”. In Java the programmer can deside if he’s got to use “Runtime”-exceptions or “hard” exceptions that have to be catched explicitly. And you can do it in Java pretty need, too, not only by polymorphism.

    Taking your first Ruby example and expanding it:

    String str = null;
    try {
    str.toString();
    Integer.parseInt(str);
    }
    catch(NullPointerException np) {
    System.out(”Hey! Gotta no value.”);
    }
    catch(NumberFormatException nf) {
    System.out(”Hey! Gotta wrong value.”);
    }
    catch(Throwable t) {
    System.out(”Hey! Something went wrong: ” + t.getMessage());
    }

    Your seven lines Ruby are fourteen lines in Java now, but I think you get the idea. And be honest, its not that complex. This and the fact that you could use polymorph exceptions should do.

    And do look at the Java-snippet: It’s pretty much explaining what goes wrong, too.

    Just my 0,02$, greetings, Jerkwood

    Jerkwood (April 3rd, 2006 at 14:11)
  8. 8

    “I would very much like to see a elegant solution which catches only java.sql.SQLException and java.util.concurrent.TimeoutException”

    try {
    foo();
    } catch(java.sql.SQLException e) {
    sqle.printStackTrace();
    } catch(java.util.concurrent.TimeoutException e) {
    e.printStackTrace();
    }

    Robert Fisher (April 3rd, 2006 at 18:51)
  9. 9

    Again, I should have been more specific :-) I usually have to do more than just print out the stacktrace. This errorhandling is sometimes the same for different Exceptions. This leads to solutions like the one below, which I don’t consider very elegant, compared to the Ruby solution:

    try {
    foo();
    } catch(java.sql.SQLException e) {
    handleEx(sqle);
    } catch(java.util.concurrent.TimeoutException e) {
    handleEx(e);
    }

    private void handleEx(Exception e) {

    }

    I would like to see:

    try {
    foo();
    } catch(java.sql.SQLException, java.util.concurrent.TimeoutException : Exception e) {

    }

    I admit, this is just syntactic sugar but I like sugar :-)

    Frank Spychalski (April 4th, 2006 at 08:16)

Any comments? Or questions? Just leave a Reply:

Bot-Check