Nick Sieger: Tag rubygemstag:blog.nicksieger.com,2005:TypoTypo2010-11-22T18:35:25+00:00Nick Siegerurn:uuid:56bbb86c-adaf-4e91-b2a4-5644bffbea7a2007-01-12T04:27:07+00:002010-11-22T18:35:25+00:00Self-cloning JRuby and RubyGems in a Jar<p>As part of <a href="http://jira.codehaus.org/browse/JRUBY-419">some work I’m doing</a> to make JRuby more portable and easier to run standalone without all the <code>$JRUBY_HOME</code> 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 <a href="http://snapshots.repository.codehaus.org/org/jruby/jruby-complete/0.9.3-SNAPSHOT/">0.9.3 jruby-complete snapshots older than 2007/01/11 only</a>.)</p>
<p>Here, give it a try:</p>
<h3>IRB in a jar</h3>
<div class="typocode"><pre><code class="typocode_default ">$ 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></code></pre></div>
<h3>RubyGems in a jar</h3>
<p>RubyGems needs a place to unpack and run gems, so JRuby currently will hide all that away from you in <code>~/.jruby</code>. (Also, unfortunately we exceed Java’s default memory size when downloading the RubyGems index file, so you’ll have to add the <code>-Xmx256m</code> argument for now to avoid an out of memory condition.)</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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</code></pre></div>
<p>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 <code>bin</code> subdirectory to your <code>$PATH</code>, and continue to use JRuby just as you would a regular Ruby installation.</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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></code></pre></div>
<h3>Tattle-tale</h3>
<p>The <code>--command</code> argument is not limited to just <code>gem</code> and <code>irb</code>. Once you’ve installed any gem that has an accompanying executable script, you can simply pass that argument as the <code>--command</code>:</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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!</code></pre></div>
<p>And lo and behold, there’s a <code>ruby_install_name</code> of <code>java</code> at the new <a href="http://tattle.rubygarden.org">Gem Tattle homepage</a>!</p>Nick Siegerurn:uuid:11809439-cf89-4dc7-9fe1-933dc6609ebc2007-03-06T03:58:00+00:002010-11-22T18:55:43+00:00ActiveRecord-JDBC 0.2.3 Released<p>ActiveRecord-JDBC version 0.2.3 has been released!</p>
<h3>Install</h3>
<p>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.</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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...</code></pre></div>
<p>See <a href="http://jruby-extras.rubyforge.org/ActiveRecord-JDBC">the new RDoc documentation on Rubyforge</a> for more information on how to use ActiveRecord-JDBC. If you’re grabbing the <a href="/articles/2007/03/06/countdown-to-1-0-jruby-0-9-8-released">new JRuby 0.9.8 release</a>, be sure you get this one as well if you plan to try out <a href="http://www.headius.com/jrubywiki/index.php/JRuby_on_Rails">JRuby on Rails</a>.</p>
<h3>Changes</h3>
<ul>
<li>Release coincides (and compatible) with JRuby 0.9.8 release</li>
<li><a href="http://rubyurl.com/0Da">8 bugs fixed</a></li>
<li>Improvements and compatibility fixes for Rails 1.2.x</li>
</ul>
<p>Comments, questions, test cases, patches and all that are welcome over on the <a href="http://rubyforge.org/mail/?group_id=2014">jruby-extras mailing list</a>.</p>Nick Siegerurn:uuid:924637a6-a799-47c7-be6c-986b51b864022009-01-10T20:04:00+00:002010-12-21T22:34:49+00:00JRuby 1.1.6: Gems-in-a-jar<p>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 <a href="http://docs.codehaus.org/display/JRUBY/2008/12/17/JRuby+1.1.6+Released">1.1.6 release last month</a>. Gems in a jar!</p>
<p><a href="http://flickr.com/photos/splorp/36991739/" title="Gem Jar">
<img src="http://farm1.static.flickr.com/26/36991739_48ab6e8fb7.jpg" alt="gemjar"/>
</a></p>
<div style="clear:both"></div>
<p><span style="font-size:75%">by <a href="http://flickr.com/photos/splorp">splorp on flickr</a></span></p>
<p>This opens up a couple new possibilities for running, packaging and deploying JRuby-based applications. Here are some ideas:</p>
<h2>Run Gem-based applications with <code>jruby-complete.jar</code></h2>
<p>JRuby has <a href="http://jira.codehaus.org/browse/JRUBY-969">bundled Rake and RSpec since version 1.0</a>. As of JRuby 1.1.6 the versions we bundle are Rake 0.8.3 and RSpec 1.1.11. With <a href="http://repository.codehaus.org/org/jruby/jruby-complete/1.1.6/jruby-complete-1.1.6.jar"><code>jruby-complete-1.1.6.jar</code></a> you can easily run these with <code>java -jar</code>:</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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] ...</code></pre></div>
<h2>Package gem collections into reusable jar files</h2>
<p>One of the features I added was to enhance RubyGems to search for directories named <code>specifications</code> on the classpath and add them to the <code>Gem.path</code> 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.)</p>
<p>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 <code>chronic</code>:</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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</code></pre></div>
<p>With this command, RubyGems created <code>chronic-gems/bin</code>, <code>chronic-gems/cache</code>, <code>chronic-gems/gems</code>, and <code>chronic-gems/specifications</code> directories and installed <code>chronic</code> and its dependencies into it. Now, simply package those directories into a jar file. <strong>WARNING</strong>: 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 <code>require 'chronic'</code>!</p>
<div class="typocode"><pre><code class="typocode_default ">$ jar cf chronic-gems.jar -C chronic .</code></pre></div>
<p>When you inspect the contents of the jar, you’ll see the gem repository structure in the root of the jar file:</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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</code></pre></div>
<p>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:</p>
<div class="typocode"><pre><code class="typocode_default ">$ # 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)</code></pre></div>
<h2>Bundle pure-Ruby gem applications into an uber-jar</h2>
<p>Taking a cue from the previous techniques, we can stuff the gem directories into a copy of <code>jruby-complete-1.1.6.jar</code> rather than creating a new jar, and distribute an entire gem-based application in a single file. Imagine something like:</p>
<div class="typocode"><pre><code class="typocode_default ">$ 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</code></pre></div>
<p>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 <code>-S</code> script so that <code>java -jar mycoolapp</code> is all that’s needed to run the application.</p>
<p>I hope you find interesting uses for this new feature. Let us know what you make with it!</p>