JRubyDynamicJarLoading

Dynamic Jar Loading in JRuby

by Teera Kanokkanjanarat

Introduction

If you plan to bundle JRuby and Java in one package, one problem you'll likely to run into is how to manage Jar dependencies. Let's assume that your Java code relies on a third party Jar component, after you build the project, this Jar will be included in a separate folder ('lib' folder). However, what if your Ruby script also has to make a call to that third party component from inside your packaged Jar file? At the time of this writing, JRuby 1.1 RC2 only supports ruby script calls to jar files within the same package, not external jars.

I got an email from a developer who ran into this exact problem. The easiest solution is to package the third party jar file at two places: one inside the package for ruby script to access, another outside the jar package for Java class. But that wouldn't be a good solution. After some thoughts and fiddling around, I came up with ruby script that can dynamically load a class and create class instance from external jar file. This way you only need to include one copy of the third party jar file outside the package.

Sample third party jar file

To demonstrate, first I create a simple Java project called 'ThirdParty' with one simple class 'Thing'. Then I build and put the result jar file outside its original location.

File:Picture 2.png

File:Picture 1.png

JRuby dynamic jar loading script

Now I create a class called
JarLoader
with one shared method {load_class}. This method takes in a string location path to jar file and class name (with package name). This class is saved as 'jar_loader.rb' file.
include Java
include_class java.net.URL
include_class java.net.URLClassLoader;
include_class java.io.File

class JarLoader

  ## Loading class from Jar file in specified file path
  def self.load_class(jar_path, class_name)
    puts 'Loading Jar from: ' + jar_path
    
    begin
      jar_url = java.io.File.new(jar_path).toURL
      #creating java.net.URL[] array
      url_array = Array[Jar_url].to_java(java.net.URL)
      class_loader = java.net.URLClassLoader.new(url_array)
      class_type = class_loader.loadClass(class_name)
      return class_type.newInstance
    rescue StandardError => err
      puts 'exception caught ' + err
      return nil
    end
  end
end

Running the script

Lastly I write a simple script to test the
JarLoader
include Java

include_class javax.swing.JFrame
include_class javax.swing.JButton
include_class 'ClassLoaderUtil'
require 'jar_loader'

# Here you need to get the location of the third party jar.
jar_location = '/Users/teera/DATA/dev/Netbeans_Projects/JRuby/DynamicJarLoader/ThirdParty.jar'
# Here you need target class name to to instantiate
class_name = 'ThirdParty.Thing'

#create two Thing object 
thing1 = JarLoader.load_class(jar_location, class_name)
thing1.setName('I am Thing1.')
thing2 = JarLoader.load_class(jar_location, class_name)
thing2.setName('I am Thing2.')

frame = JFrame.new("Swing with JRuby")
frame.setSize(400, 400)
label = javax.swing.JLabel.new("label");
label.setText(thing1.toString + ' ' + thing2.toString)

#display
frame.get_content_pane.add(label)
frame.set_default_close_operation(JFrame::EXIT_ON_CLOSE)
frame.pack
frame.visible = true

When this sample code is run, the Thing objects from the third party jar will be created.

File:Picture 3.png

You can download code sample from the attachment. For questions, comments, and feedback, please drop me an email at teera dot tk at gmail dot com.


Have a programming question or need help using Sun products or community technologies in your development projects? Get Sun Developer Expert Assistance! This online support service for developers provides technical assistance for code support, programming questions, and diagnostic advice to resolve problems. Buy Now


Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo