JRuby 1.1.6: Gems-in-a-jar

Posted by Nick Sieger Sat, 10 Jan 2009 20:04:00 GMT

As a result of some fruitful hacking at RubyConf 2008, I was able to modify JRuby so that gems can be loaded and used without having to unpack them. The feature became generally available with the 1.1.6 release last month. Gems in a jar!

gemjar

by splorp on flickr

This opens up a couple new possibilities for running, packaging and deploying JRuby-based applications. Here are some ideas:

Run Gem-based applications with jruby-complete.jar

JRuby has bundled Rake and RSpec since version 1.0. As of JRuby 1.1.6 the versions we bundle are Rake 0.8.3 and RSpec 1.1.11. With jruby-complete-1.1.6.jar you can easily run these with java -jar:

$ java -jar jruby-complete-1.1.6.jar -S rake --help
rake [-f rakefile] {options} targets...

Options are ...

$ java -jar jruby-complete-1.1.6.jar -S spec --help
Usage: spec (FILE|DIRECTORY|GLOB)+ [options]

    -p, --pattern [PATTERN] ...

Package gem collections into reusable jar files

One of the features I added was to enhance RubyGems to search for directories named specifications on the classpath and add them to the Gem.path automatically. This means you can package up a whole gem repository into a jar file for easy reuse and sharing of commonly used gems. There isn’t a tool for this yet, but the process is pretty straightforward. (If someone plays with this and can come up with a patch to build this into JRuby, we’ll gladly accept one.)

First, create a gem repository by installing the gems you want into it. Let’s say you want to package the natural language date/time parser chronic:

$ java -jar jruby-complete-1.1.6.jar -S gem install -i ./chronic-gems chronic --no-rdoc --no-ri
Successfully installed rubyforge-1.0.2
Successfully installed rake-0.8.3
Successfully installed hoe-1.8.2
Successfully installed chronic-0.2.3
4 gems installed

With this command, RubyGems created chronic-gems/bin, chronic-gems/cache, chronic-gems/gems, and chronic-gems/specifications directories and installed chronic and its dependencies into it. Now, simply package those directories into a jar file. WARNING: make sure you don’t give the jar file name the same basename as the library or gem inside you wish to use (e.g., chronic.jar), because JRuby will load chronic.jar when you require 'chronic'!

$ jar cf chronic-gems.jar -C chronic .

When you inspect the contents of the jar, you’ll see the gem repository structure in the root of the jar file:

$ jar tf chronic-gems.jar | head
META-INF/
META-INF/MANIFEST.MF
bin/
bin/rake
bin/rubyforge
bin/sow
cache/
cache/chronic-0.2.3.gem
cache/hoe-1.8.2.gem
cache/rake-0.8.3.gem

Chronic is now a re-useable jar library that can be easily loaded, either by requiring the jar in ruby code or adding to the classpath:

$ # Without chronic-gems.jar
$ java -jar jruby-complete-1.1.6.jar -S gem list

*** LOCAL GEMS ***

rake (0.8.3)
rspec (1.1.11)
sources (0.0.1)

$ # With chronic-gems.jar
$ java -jar jruby-complete-1.1.6.jar -rchronic-gems.jar -S gem list

*** LOCAL GEMS ***

chronic (0.2.3)
hoe (1.8.2)
rake (0.8.3)
rspec (1.1.11)
rubyforge (1.0.2)
sources (0.0.1)

Bundle pure-Ruby gem applications into an uber-jar

Taking a cue from the previous techniques, we can stuff the gem directories into a copy of jruby-complete-1.1.6.jar rather than creating a new jar, and distribute an entire gem-based application in a single file. Imagine something like:

$ java -jar jruby-complete-1.1.6.jar -S gem install -i ./mycoolapp mycoolapp
$ jar uf jruby-complete-1.1.6.jar -C mycoolapp .
$ mv jruby-complete-1.1.6.jar mycoolapp.jar
$ java -jar mycoolapp.jar -S mycoolapp

Bonus points to the enterprising individual who provides a patch to make this a one-step process, including creating a mechanism to provide a default -S script so that java -jar mycoolapp is all that’s needed to run the application.

I hope you find interesting uses for this new feature. Let us know what you make with it!

Tags ,

ActiveRecord-JDBC 0.2.3 Released

Posted by Nick Sieger Tue, 06 Mar 2007 03:58:00 GMT

ActiveRecord-JDBC version 0.2.3 has been released!

Install

Use JRuby to install the gem into your JRuby installation as follows. Currently, Rails is not a dependency of ActiveRecord-JDBC; it is assumed you’re going to have Rails installed already.

$ jruby --command gem install ActiveRecord-JDBC
Successfully installed ActiveRecord-JDBC-0.2.3
Installing ri documentation for ActiveRecord-JDBC-0.2.3...
Installing RDoc documentation for ActiveRecord-JDBC-0.2.3...

See the new RDoc documentation on Rubyforge for more information on how to use ActiveRecord-JDBC. If you’re grabbing the new JRuby 0.9.8 release, be sure you get this one as well if you plan to try out JRuby on Rails.

Changes

  • Release coincides (and compatible) with JRuby 0.9.8 release
  • 8 bugs fixed
  • Improvements and compatibility fixes for Rails 1.2.x

Comments, questions, test cases, patches and all that are welcome over on the jruby-extras mailing list.

Tags , ,  | 6 comments | no trackbacks

Self-cloning JRuby and RubyGems in a Jar

Posted by Nick Sieger Fri, 12 Jan 2007 04:27:07 GMT

As part of some work I’m doing to make JRuby more portable and easier to run standalone without all the $JRUBY_HOME launcher scripts, it’s now easier than ever to get up and running with JRuby, or to launch in your build scripts or IDE in a platform-neutral way. (Note: as of this writing, this feature is in 0.9.3 jruby-complete snapshots older than 2007/01/11 only.)

Here, give it a try:

IRB in a jar

$ curl -o jruby-complete.jar http://snapshots.repository.codehaus.org/org/jruby/jruby-complete/0.9.3-SNAPSHOT/jruby-complete-0.9.3-20070112.032908-4.jar
$ java -jar jruby-complete.jar --command irb
irb(main):001:0>

RubyGems in a jar

RubyGems needs a place to unpack and run gems, so JRuby currently will hide all that away from you in ~/.jruby. (Also, unfortunately we exceed Java’s default memory size when downloading the RubyGems index file, so you’ll have to add the -Xmx256m argument for now to avoid an out of memory condition.)

$ java -Xmx256m -jar jruby-complete.jar --command gem install tattle -y --no-rdoc --no-ri
creating /Users/nicksieger/.jruby/bin/gem
... more files extracted ...
copying /Users/nicksieger/jruby-complete.jar to /Users/nicksieger/.jruby/lib
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed tattle-1.0.1
Successfully installed hoe-1.1.7
Successfully installed rubyforge-0.4.0
Successfully installed rake-0.7.1

You can still have JRuby unpack to a shared directory if you like, and use the regular shell scripts for launching JRuby. In this case, JRuby is actually replicating itself into the directory you choose. Simply add the bin subdirectory to your $PATH, and continue to use JRuby just as you would a regular Ruby installation.

$ sudo java -jar jruby-complete.jar --command extract /opt/local/jruby
Password:
creating /opt/local/jruby/bin/gem
... more files extracted ...
copying /Users/nicksieger/jruby-complete.jar to /opt/local/jruby/lib
$ PATH=/opt/local/jruby/bin:$PATH
$ which gem
/opt/local/jruby/bin/gem
$ jirb
irb(main):001:0>

Tattle-tale

The --command argument is not limited to just gem and irb. Once you’ve installed any gem that has an accompanying executable script, you can simply pass that argument as the --command:

$ java -jar jruby-complete.jar --command tattle report
ruby_install_name, jruby
LIBRUBY, jruby
target, java
arch, java
host_vendor, Apple Computer, Inc.
key, b1bd5eaf4254d9874ca297995b906be6f4975d395dd0136432f859c62a33cc8c
host_os, Mac OS X
ruby_version, 1.8.5
build, java
target_cpu, i386
prefix, /Users/nicksieger/.jruby
report_time, Thu Jan 11 22:21:57 CST 2007
rubygems_version, 0.9.0
host_cpu, i386
LIBRUBY_SO, jruby
SHELL, /bin/sh
$ java -jar jruby-complete.jar --command tattle
Posting information to Tattle server.  Thanks!

And lo and behold, there’s a ruby_install_name of java at the new Gem Tattle homepage!

Tags , ,  | 2 comments | no trackbacks