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.
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.
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
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.
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
| DynamicJarLoader.zip | ![]() |
18363 bytes |
| Picture 1.png | ![]() |
58706 bytes |
| Picture 2.png | ![]() |
63222 bytes |
| Picture 3.png | ![]() |
10481 bytes |