Keeping it Small and Simple

2007.05.24

Dealing with Java exceptions in JRuby

Filed under: Java Programming, JRuby, Ruby Programming — Lorenzo E. Danielsson @ 16:32

As you may know already, JRuby gives you access to the Java class library, so that you can do things like write Swing applications in Ruby. Of course, that also means that your JRuby code needs to deal with the exceptions that various Java classes can throw.

Exception handling is similar in Ruby and Java, but there are a few small differences. If you know both Java and Ruby you already know that in Java we use try and catch whereas in Ruby we use begin and rescue. But the principle is the same. Any code that could throw and excpetion goes into a try (or begin) block. If an exception is thrown, execution moves to the corresponding catch (rescue) block.

But Java has two slightly different types of exceptions: “normal” exceptions and runtime exceptions. The difference is that if you call anything that can throw java.lang.Exception or one of its subclasses, then you must enclose that code in a try-catch block. So, for instance, the following code will not compile:

1 public class ForNameTest {
2     public static void main(String[] args) {
3         Class.forName("java.lang.String");
4     }
5 }

Trying to compile we get:

% javac ForNameTest.java
ForNameTest.java:3: unreported exception java.lang.ClassNotFoundException; must be caught or declared to be thrown
        Class.forName("java.lang.String");
                     ^
1 error

In Ruby, however, it is not required to put any code within a begin-rescue block (in other words, Ruby treats all exceptions as they were Java runtime exceptions). Here is the equivalent JRuby code:

1 #! /usr/local/bin/jruby -w
2 
3 require 'java'
4 
5 java::lang::Class.forName("java.lang.String")

This will run without any problems. Notice another thing. I have specified the fully qualified name of the Java Class class. The reason is simple. Both Ruby and Java contain a class called Class. If I don’t qualify it, JRuby will assume that I want to use the Ruby class, which does not contain a forName method. Keep that in mind when there is both a Ruby class and a Java class with the same name.

Also note that just because we don’t have to use a begin-rescue in Ruby doesn’t mean that it is not a good idea. On the contrary, you should use exception handling to trap errors and do something useful when they occur.

Apart from that, dealing with Java exceptions in JRuby is very straightforward. Look at the following example:

 1 #! /usr/local/bin/jruby -w
 2 
 3 require 'java'
 4 
 5 include_class 'java.lang.ClassNotFoundException'
 6 
 7 begin
 8   # This will work.
 9   java::lang::Class.forName("java.lang.String")
10 
11   # This will not.
12   java::lang::Class.forName("foo.Bar")
13 rescue ClassNotFoundException => e
14   $stderr.print "Java told me: #{e}n"
15 end

Simple, wasn’t it? The first call to forName is not problematic because java.lang.String is a valid class name. The second call will fail, because under normal circumstances we don’t have a foo.Bar class (unless you have added one).

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.