The worlds first cheese board with DRM built in 1

Posted by Michael Studman Sat, 30 Sep 2006 09:08:55 GMT

Microsoft's Zune - perfect for hard and soft cheeses

Handling Java exceptions in JRuby 2

Posted by Michael Studman Tue, 26 Sep 2006 23:54:00 GMT

At my enterprisey day job I’m finding the JRuby platform to be the perfect glue for bringing together a (sadly necessary) slew of Java libraries and middleware (3rd-party Ant tasks, Jakarta VFS, ServiceMix, Maven, Weblogic) to solve a complex problem crucial to our enterprise. Stellar support for exception handling is obviously important when integrating so many libraries and middleware so how well does JRuby help with this? Is it just a Java fair-weather friend?

Thankfully the answer is no. JRuby allows you to catch Java exceptions in Ruby code and handle them as if they were Ruby exceptions. These Ruby-ised exceptions provide, for free, a backtrace which spans your Ruby stack and your Java stack.

The least intrusive way to handle Java exceptions is to just pretend it’s a Ruby exception:

  require 'java'

  begin
    # some bad Java mojo
  rescue RuntimeError => e
    puts "Java or Ruby exception: #{e}"
    raise
  end

require ‘java’ loads in Java support from within JRuby and is necessary any time you want to call Java code.

All Java exceptions, when caught in the ether between your Ruby code that made the call and the Java code that fielded the code, is wrapped in a subclass of RuntimeError (more on this in a moment) and raised. By rescuing RuntimeError you are catching any Java exceptions that were thrown. Of course you’re also rescuing all Ruby RuntimeError exceptions that were thrown in the block too.

If you wish to segregate your Java exceptions from those raised from Ruby code then JRuby provides support for this too.

  require 'java'

  begin
    # some bad Java mojo
  rescue NativeException => e
    puts "Native exception's cause: #{e.cause}"
  end

NativeException is a JRuby-specific Ruby exception which wraps any Java exception and provides access to it via the ‘cause’ method. It is the RuntimeError subclass caught in the first example. If you rescue a NativeException you will thus be rescuing all Java exceptions thrown from within the begin / rescue block but no others.

The cause methods provides access to the underlying Java exception. Unfortunately version 0.9.0 of JRuby has a small shortcoming with this. The Java exception returned by cause is not in a form that enables you to easily call its Java methods (ie its not proxied in JRuby). I think this is an enhancement that needs looking at and I have raised JIRA issue 104 accordingly.

In the mean time, the following code should give you and idea of how to access the underlying Java exception in a Ruby-friendly fashion:

  begin
    # some bad Java mojo
  rescue NativeException => e

    #creates a Ruby proxy for the Java exception
    proxied_e = JavaUtilities.wrap(e.cause)

    proxied_e.print_stack_trace
  end

The final and most natural way of handling a Java exception is by making JRuby aware of it and then rescuing it like you would a regular Ruby exception:

  require 'java'
  include_class 'java.lang.IOException'

  begin
    # bad IOException-inducing mojo
  rescue IOException => e
    puts "Java IO exception: #{e.message}"
  end

include_class takes the Java class ‘java.lang.IOException’ and makes it available to your Ruby code through the name ‘IOException’.

By rescuing an IOException and assigning it to a variable ‘e’ you get an instance of NativeException with a cause method returning the native java.io.IOException. I think this is slightly confusing as you asked to rescue an IOException but got a NativeException - e should really be a proxied java.io.IOException but I can see some implementation difficulties with this when I think about it. I may raise this issue with Charles and Thomas.

Again e.cause isn’t proxied but a call to JavaUtilities.wrap(e.cause) will fix that.

So it’s that simple! JRuby provides great integration with Java’s exception system although it obviously needs a small amount of polish before it will be completely seamless. Onward and upward!

Java snippet: Debugging a Java library used from Ant

Posted by Michael Studman Fri, 01 Sep 2006 13:05:02 GMT

I recently needed to debug a library which seemed to be misbehaving when used within Ant. After a bit of research here’s the best way I found to debug within Ant that doesn’t require sprinkling your bin/ant or bin\ant.bat with temporary JPDA pixy dust.

Ant doesn’t directly accept the -X arguments needed to set up the JPDA settings so the question is: how do you pass these from a shell or command line? In this, the ANT_OPTS environment variable is your friend. Its contents will be directly passed to the Java process Ant calls.

So here’s how you do it:

Step 1: Set ANT_OPTS to the debug options appropriate for your JVM:

for Java 1.4:

>> export ANT_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8453

for Java 1.5:

>> export ANT_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8453

Step 2: Run ant like normal:

  
>> ant

Step 3: Set your breakpoints.

Step 4: Now attach your debugger.

There might be better ways to do this but this was the least invasive route for me.