2

Someone on my team is writing a ruby/cucumber test that calls a java api that takes a List<Long> argument. I'm trying to help him out but my jruby knowledge is pretty limited. Whenever the call to the java method that takes List<Long> is made the java method is throwing some sort of class cast exception because the ArrayList contains all ruby Fixnum objects.

The following simplified code shows that I always get a Fixnum not a Java::JavaLang::Long

irb(main):017:0> java.util.ArrayList.new([12.to_java])[0].class
=> Fixnum

This is even though the following shows that 12.to_java produces a Long

irb(main):018:0> 12.class
=> Fixnum
irb(main):019:0> 12.to_java.class
=> Java::JavaLang::Long 

I've also tried not using the constructor args

irb(main):020:0> a = java.util.ArrayList.new
=> #<Java::JavaUtil::ArrayList:0x314e60d2>
irb(main):021:0> a.add(12.to_java)
=> true
irb(main):022:0> a[0].class
=> Fixnum

And gone as far a just instantiating a java.lang.Long directly

irb(main):023:0> a = java.util.ArrayList.new
=> #<Java::JavaUtil::ArrayList:0xfdcb343>
irb(main):024:0> a.add(java.lang.Long.new(12))
=> true
irb(main):025:0> a[0].class
=> Fixnum

And my last attempt

irb(main):026:0> b = 12.to_java
=> #<Java::JavaLang::Long:0x244ff48e>
irb(main):027:0> b.class
=> Java::JavaLang::Long
irb(main):028:0> a = java.util.ArrayList.new
=> #<Java::JavaUtil::ArrayList:0x6a36ebaa>
irb(main):029:0> a.add b
=> true
irb(main):030:0> a.get(0).class
=> Fixnum
1
  • The above issue was a rabbit hole and not the real problem (as I suspected). I've selected the more detailed answer below. I still don't know why 12.to_java produces a Java::JavaLang:Long but when that gets put in a java List it is converted back to a Fixnum. But that was definitely not the issue as shown by @kares Commented Dec 11, 2014 at 13:55

1 Answer 1

2

actually, this is far easier than you think and will work fine if you just pass a [] around :)

while on the Ruby side JRuby makes sure values are Ruby-like but when it reaches the Java end - in case of a RubyArray instance passed to Java (which actually implements java.util.List) - it will auto-convert "toJava" at it's best. means for Ruby Fixnums you will get java.lang.Long on operations such as java.util.List#get :

public class JavaAPI {
    public void testListArgument(final List<Long> list) {
        System.out.println("list = " + list + " list.class = " + list.getClass() + " list[0].class = " + list.get(0).getClass());
    }
}

compile this .java (under target/classes) than doing something like jruby -S irb :

jruby-1.7.16 :007 > $CLASSPATH << 'target/classes'
 => ["file:/opt/local/rvm/rubies/jruby-1.7.16/lib/ruby/shared/readline/jline-2.11.jar", "file:/opt/local/rvm/rubies/jruby-1.7.16/lib/ruby/shared/readline/readline.jar", "file:target/classes/"] 
jruby-1.7.16 :009 > Java::JavaAPI.new.testListArgument [1]
list = [1] list.class = class org.jruby.RubyArray list[0].class = class java.lang.Long
 => nil 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.