I've been trying to get a JRuby script that is very simple in nature that requires Net::SSH to perform a task on a remote computer and exit. When I issue the command jruby testssh.rb
, the program works flawlessly, however, when I use Warbler to compile it into a JAR, I receive errors about not being able to load Net::SSH.
> java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
> pik use jruby-1.7.1
> jruby -S warble jar
C:/ruby/jruby-1.7.10/lib/ruby/gems/shared/gems/rawr-1.7.0/lib/zip/zip.rb:28: Use RbConfig instead of obsolete and deprecated Config.
rm -f test-ssh.jar
Creating test-ssh.jar
> java -jar test-ssh.jar
LoadError: no such file to load -- net/ssh
require at org/jruby/RubyKernel.java:1085
require at file:/C:/Users/User/AppData/Local/Temp/jruby4935218336857439685extract/jruby-stdlib-complete-1.7.11.jar!/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55
(root) at test-ssh.rb:7
load at org/jruby/RubyKernel.java:1101
(root) at file:/C:/Users/User/Dropbox/programming/ruby/jruby/net-ssh/test-ssh/test-ssh.jar!/META-INF/main.rb:1
require at org/jruby/RubyKernel.java:1085
(root) at file:/C:/Users/User/AppData/Local/Temp/jruby4935218336857439685extract/jruby-stdlib-complete-1.7.11.jar!/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:1
require at file:/C:/Users/User/AppData/Local/Temp/jruby4935218336857439685extract/jruby-stdlib-complete-1.7.11.jar!/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55
error: org.jruby.embed.EvalFailedException: (LoadError) no such file to load -- net/ssh
I then put the files into a gem, and added the spec.add_runtime_dependency = "net-ssh"
to the gemspec, and:
require 'net/ssh'
gem "net-ssh"
into the Gemfile. Then when I run jruby -S warble
, I get a different error. I also noticed, Bundler, and Ruby didn't play well with the '-' in the name, so I had to recreate the file again.
> jruby -S warble
C:/ruby/jruby-1.7.10/lib/ruby/gems/shared/gems/rawr-1.7.0/lib/zip/zip.rb:28: Use RbConfig instead of obsolete and deprecated Config.
No default executable found in test-ssh.gemspec, using bin/test-ssh.rb
rm -f test-ssh.jar
Creating test-ssh.jar
> java -jar testssh.jar
LoadError: no such file to load -- testssh/bin/testssh.rb
load at org/jruby/RubyKernel.java:1101
(root) at file:/C:/Users/User/Dropbox/programming/ruby/jruby/net-ssh/testssh/testssh.jar!/META-INF/main.rb:1
require at org/jruby/RubyKernel.java:1085
(root) at file:/C:/Users/User/AppData/Local/Temp/jruby6762643836642223701extract/jruby-stdlib-complete-1.7.11.jar!/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:1
require at file:/C:/Users/User/AppData/Local/Temp/jruby6762643836642223701extract/jruby-stdlib-complete-1.7.11.jar!/META-INF/jruby.home/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55
error: org.jruby.embed.EvalFailedException: (LoadError) no such file to load -- testssh/bin/testssh.rb
I'm at a loss for what needs to be done, and I've found a lot of half-baked answers for questions similar to this, or people who have left bugs about this on the Warbler github page for more than a year with no answers.
The Gist with the code and errors are located here: https://gist.github.com/predatorian3/10191754
The solution was:
The way bundler creates Ruby gems is that it utilizes Git, and I wasn't using git add .
to include all the changed directories. Once I did git add .
and git commit
, Warbler picked up those directories that it was missing the first go around. Then for gem dependency, it was as simple as editing the .gemspec file, and including runtime_dependency
for each gem that I had required into my own gem. After that, Warbler included those dependencies, and the JAR file can run without JRuby installed.
It needs some file that it can run when you run the jar! You can specify one in the gemspec, but it will default to bin/.rb. No such file exists, thus the error.