Forum: JRuby JRuby integration problem

Posted by Mathew D. (mathew_d)
on 2012-09-10 05:52
(Received via mailing list)
Hello all,
 Sorry if this is a (too) long message.

First a little background on my problem...

I have some java code that I'd like to wrap with jruby (eventually so I 
can
use it in a jruby on rails app, but that's not relevant at the moment).
Essentially, I am trying to do the following

I 'require java'
I iterate across all the jar files I should need in the lib directory of 
my
project with  'Dir["lib/\*.jar"].each { |jar| require jar }'

I 'java_import my.package.and.className'

however, when I try to use my class, it calls out to a delegate class to
take care of some initialization/singleton stuff (I didn't write it, so
don't blame me).  The problem is I wind up with this error
NativeException: java.lang.RuntimeException: Unexpected
ClassNotFoundException looking up class 'org/jruby/Main'

I can only guess that the init code is doing something seriously funky,
which is why JRuby can't find it's own running class (assuming I'm 
reading
the error correctly).  Any ideas for dealing with this are greatly
appreciated.

Now the immediate problem...

So far, I've tried setting the log4j level to debug, so I could get a
better idea of where in the java code, the errors are actually coming 
from.
 That has proven to be more difficult than I imagined.
I used this code to set the log level, and print it back out, so I know 
it
at least thinks the setting took

org.apache.log4j.LogManager.getLogger("my.package.className.class").setLevel(org.apache.log4j.Level.toLevel("DEBUG"))
puts "Log level is "+
org.apache.log4j.LogManager.getLogger("my.package.className.class").getEffectiveLevel.toString
Indeed, that does print out 'DEBUG', however, I'm still only seeing log
messages from my java code at INFO level.

I also threw a log4j.properties file in the directory and load it as
    file = File.new("log4j.properties");
    PropertyConfigurator.configure(file.toURL());
    logger = Logger.getLogger("java_integ_test.rb");
    logger.debug("Test of debug msg");

and it does seem to print out the debug message.  I use that config file 
to
set the root logger to DEBUG level

log4j.rootLogger=DEBUG, stdout
log4j.logger.com=DEBUG

However, I'm still not getting any debug messages from my java code 
(only
the ruby script itself)

So, my two questions are.
1) how the @#$% can I get the logger to run in debug for my java code
2) Any idea on what the first error actually means?

I strongly suspect that if I can get 1 answered, then 2 will follow 
easily.


I doubt that it matters, but I'm running jruby-1.6.7 [ 
darwin-x86_64-java ]
on OSX.  The behavior is the same for both Mountain Lion with Java 1.7, 
and
Lion with Java 1.6.

Thanks for reading this far,
  Mat
Posted by Keith B. (keith_b)
on 2012-09-10 06:32
(Received via mailing list)
Mathew -

I think your problem is the backslash in the argument to Dir[]. Why do
you have it there?  I think you only want:

Dir["lib/*.jar"]

- Keith

--
Keith R. Bennett
http://about.me/keithrbennett
Posted by Mathew D. (mathew_d)
on 2012-09-10 06:57
(Received via mailing list)
I have corrected that, but the behavior appears to be unchanged.

As a test, I created a new lib directory, and changed my classpath code 
to
Dir["./lib2/*.jar"].each { |jar|
  require jar
  puts jar.inspect
}

Now, if I run my jruby with -d, I see these errors(?), even though the 
file
is there, and being seen.

java.lang.ClassNotFoundException: lib2.Slf4j-log4j12-1.6.4Service
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at org.jruby.util.JRubyClassLoader.findClass(JRubyClassLoader.java:86)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.jruby.javasupport.JavaSupport.loadJavaClass(JavaSupport.java:136)
at
org.jruby.runtime.load.LoadService$ExtensionSearcher.trySearch(LoadService.java:597)
at 
org.jruby.runtime.load.LoadService.findFileForLoad(LoadService.java:283)
at org.jruby.runtime.load.LoadService.smartLoad(LoadService.java:330)
at org.jruby.runtime.load.LoadService.require(LoadService.java:379)
at 
org.jruby.runtime.load.LoadService.lockAndRequire(LoadService.java:304)
at org.jruby.RubyKernel.requireCommon(RubyKernel.java:1050)
at org.jruby.RubyKernel.require(RubyKernel.java:1033)
at
org.jruby.RubyKernel$s$1$0$require.call(RubyKernel$s$1$0$require.gen:65535)
at
org.jruby.internal.runtime.methods.JavaMethod$JavaMethodOneOrNBlock.call(JavaMethod.java:319)
at 
org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:167)
at $_dot_.java_test.block_0$RUBY$__file__(./java_test.rb:9)
at
$_dot_$java_test$block_0$RUBY$__file__.call($_dot_$java_test$block_0$RUBY$__file__:65535)
at org.jruby.runtime.CompiledBlock.yield(CompiledBlock.java:112)
at org.jruby.runtime.CompiledBlock.yield(CompiledBlock.java:95)
at org.jruby.runtime.Block.yield(Block.java:130)
at org.jruby.RubyArray.eachCommon(RubyArray.java:1608)
at org.jruby.RubyArray.each(RubyArray.java:1615)
at org.jruby.RubyArray$i$0$0$each.call(RubyArray$i$0$0$each.gen:65535)
at
org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:302)
at
org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:144)
at
org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:153)
at $_dot_.java_test.__file__(./java_test.rb:8)
at $_dot_.java_test.load(./java_test.rb)
at org.jruby.Ruby.runScript(Ruby.java:697)
at org.jruby.Ruby.runScript(Ruby.java:690)
at org.jruby.Ruby.runNormally(Ruby.java:597)
at org.jruby.Ruby.runFromMain(Ruby.java:446)
at org.jruby.Main.doRunFromMain(Main.java:369)
at org.jruby.Main.internalRun(Main.java:258)
at org.jruby.Main.run(Main.java:224)
at org.jruby.Main.run(Main.java:208)
at org.jruby.Main.main(Main.java:188)
"./lib2/slf4j-log4j12-1.6.4.jar"


The last line shows that the script could see the jar file. I get this
error for each jar file I have in my new lib2 directory.  I'm unsure if
this is a real error, if my jruby install is mucked up.

Mat
Posted by Pradeep Singh (pradeeplogs)
on 2012-09-10 07:03
(Received via mailing list)
Why's it looking for a class that starts with lib2 as the main package -
 lib2.Slf4j-log4j12-1.6.4Service

Try using an absolute path. I am using this in my rails application and 
it
seems to be fine with the jars I have in place -

Dir["#{File.dirname(__FILE__)}/../lib/jars/*.jar"].each do |jar|
  require jar
end
Posted by Mathew D. (mathew_d)
on 2012-09-10 07:22
(Received via mailing list)
Good point.

I reinstalled jruby through rvm (it's now 1.6.4 as the default version). 
I
changed my code based off of what you have below.
On the upside, those 'errors' are now gone from the startup, but the end
result is still the same (same error as before
NativeException: java.lang.RuntimeException: Unexpected
ClassNotFoundException looking up class 'org/jruby/Main'
  (root) at ./java_test.rb:28 )

Also, I don't know if it matters, but when I added a 'puts jar.inspect' 
in
the classpath code, it's still printing as relative.
"./lib/xercesImpl-2.9.1.jar"
"./lib/xml-apis-1.3.04.jar"

I hardcoded the path, to the full path to the lib dir, and now they are
showing with their full paths, but no real difference in behavior.

I feel like we're cutting down on the noise around the real problem, but 
so
far, it's still I'm still flummoxed.

Thanks
Mat
Posted by Pradeep Singh (pradeeplogs)
on 2012-09-10 07:37
(Received via mailing list)
FWIW, I ended up using a checkout from the repository and doing a local
JRuby build and setting it in the PATH.

Can you give a full trace for the error? The bigger the better.
Posted by Pradeep Singh (pradeeplogs)
on 2012-09-10 07:40
(Received via mailing list)
Your jruby.jar is in the CLASSPATH, right?
Posted by Mathew D. (mathew_d)
on 2012-09-10 07:45
(Received via mailing list)
I'm not getting any stack traces now.  The sum total of the error (when
running with -d is the one shown below).
NativeException: java.lang.RuntimeException: Unexpected
ClassNotFoundException looking up class 'org/jruby/Main'
  (root) at ./java_test.rb:28 )

Also, I copied the jruby.jar to the lib dir (just to be on the safe 
side),
where all the other jars are, and that didn't seem to make any 
difference
in behavior.

Mat
Posted by kristian (Guest)
on 2012-09-10 08:05
(Received via mailing list)
On Mon, Sep 10, 2012 at 11:14 AM, mathew duafala <mduafala@gmail.com> 
wrote:
> NativeException: java.lang.RuntimeException: Unexpected
> ClassNotFoundException looking up class 'org/jruby/Main'

this error I saw when I do something like
$ java -cp 
../../../nexus/lib/slf4j-api-1.6.4.jar:~/.m2/repository/org/jruby/jruby-complete/1.7.0.preview2/jruby-complete-1.7.0.preview2.jar
org.jruby.Main -e "puts 123"
Exception in thread "main" java.lang.NoClassDefFoundError: 
org/jruby/Main
Caused by: java.lang.ClassNotFoundException: org.jruby.Main


but
$ java -cp 
~/.m2/repository/org/jruby/jruby-complete/1.7.0.preview2/jruby-complete-1.7.0.preview2.jar:../../../nexus/lib/slf4j-api-1.6.4.jar
org.jruby.Main -e "puts 123"123


since  read you both were talking about CLASSPATH - make sure jruby is
FIRST on the classpath.

about the require and the absolute path - I usually write
p require jar
as debug to see if my jar is loaded.

- Kristian
Posted by Pradeep Singh (pradeeplogs)
on 2012-09-10 08:06
(Received via mailing list)
Hopefully you'll get an answer from an expert. I've personally never 
been
able to use debug mode with JRuby.

But in any case, don't let the jruby.jar be added more than once. I 
guess
the regular Java rules must apply.
Posted by Mathew D. (mathew_d)
on 2012-09-10 08:13
(Received via mailing list)
Holy Cow, it finally works with this command!

java -cp ./lib/jruby-complete-1.6.7.2.jar  org.jruby.Main -S 
./java_test.rb

I'm not sure I understand why it needed this specific invocation.

I still don't understand why the log4j stuff didn't work, but I'm ok 
with
that at the moment.

Thanks for you're help everyone.

Mat
Posted by Pradeep Singh (pradeeplogs)
on 2012-09-10 08:17
(Received via mailing list)
I have set jruby.jar in my CLASSPATH so that I don't have to bother with
it. Other jars get loaded in the application as and when another 
required.

For your log4j, send another email specifically about that. You might 
have
a point there.
Posted by kristian (Guest)
on 2012-09-10 08:30
(Received via mailing list)
I guess that is my personal way of using jruby-complete :) - I never
used rvm so can not help you there.

you can have a bit shorted :)

java -jar ./lib/jruby-complete-1.6.7.2.jar ./java_test.rb

just do not require 'jruby.jar' as Singh wrote.

if you provide the java_test.rb as gist or pastebin and the list of
jars in ./lib/ then I will look into why the 'jruby' invoker did not
work ;)

- Kristian
Posted by Keith B. (keith_b)
on 2012-09-10 08:48
(Received via mailing list)
Strange...I thought 1.6.7 is the default version installed by rvm.

rvm is great; I highly recommend using it when working with JRuby
because it saves you from having to do all that special stuff, such as
saying jruby instead of ruby, and using jruby -S rake instead of just 
rake.

I'd suggest doing:

rvm install jruby-1.6.7

...and then make an alias for it for easier use, and for easier
upgrading to future versions:

rvm alias create jruby jruby-1.6.7

You can make it the default for each new shell like this:

rvm --default jruby

Then you should be able to run your code more easily, such as:

ruby java_test.rb

You shouldn't need the "./" because you're not running it as a Unix
command, you're just passing the filespec of the script to the JRuby
interpreter.

Also, regarding the log4j problem, I'd examine your configuration to see
if something may be wrong.  As Pradeep noticed, this:

java.lang.ClassNotFoundException: lib2.Slf4j-log4j12-1.6.4Service

implies that the program is trying to use the class
"Slf4j-log4j12-1.6.4Service" in the package "lib2".

Are you maybe specifying a filespec instead of a class in the 
configuration?

- Keith

--
Keith R. Bennett
http://about.me/keithrbennett
Posted by kristian (Guest)
on 2012-09-10 09:59
(Received via mailing list)
just one last thought (hope these many emails are not does not annoy 
you).

why not using
https://github.com/mkristian/jbundler
to manage you jar files. it will take care of loading the jars.

- Kristian
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.