Skip to content

JRuby examples don't work (JRuby picks the wrong overloaded method) #320

Closed
@iconara

Description

@iconara

The JRuby adapter doesn't work because JRuby can't figure out which overloaded Observable#subscribe method to pick. It ends up picking Observable#subscribe(Map<String, Object>), which raises an error because the argument doesn't respond right:

require 'rxjava-core-0.10.0.jar'
require 'rxjava-jruby-0.10.0.jar'

observable = Java::Rx::Observable.toObservable(['one', 'two', 'three'])
observable.take(2).subscribe(lambda { |x| puts x })

the code above prints the following errors in JRuby 1.7.4:

% ruby rxjava.rb
rxjava.rb:6 warning: ambiguous Java methods found, using subscribe(java.util.Map)
onNext
Observable.java:278:in `subscribe': java.lang.RuntimeException: 'onNext' key must contain an implementation
    from NativeMethodAccessorImpl.java:-2:in `invoke0'
    from NativeMethodAccessorImpl.java:57:in `invoke'
    from DelegatingMethodAccessorImpl.java:43:in `invoke'
    from Method.java:601:in `invoke'
    from JavaMethod.java:455:in `invokeDirectWithExceptionHandling'
    from JavaMethod.java:316:in `invokeDirect'
    from InstanceMethodInvoker.java:61:in `call'
    from MethodHandle.java:599:in `invokeWithArguments'
    from InvocationLinker.java:153:in `invocationFallback'
    from rxjava.rb:5:in `__file__'
    from rxjava.rb:-1:in `load'
    from Ruby.java:807:in `runScript'
    from Ruby.java:800:in `runScript'
    from Ruby.java:669:in `runNormally'
    from Ruby.java:518:in `runFromMain'
    from Main.java:390:in `doRunFromMain'
    from Main.java:279:in `internalRun'
    from Main.java:221:in `run'
    from Main.java:201:in `main'

in JRuby 1.6.8 it prints a less verbose version of the same error.

Notice the line which reads "onNext". That's actually the puts from lambda { |x| puts x } in action. JRuby wraps the lambda in something that looks like a Map, and then when RxJava calls get on that map JRuby calls call on the lambda.

So if you modify the example code to read lambda { |x| lambda { |y| puts y } } this is what happens:

% ruby rxjava.rb
rxjava.rb:6 warning: ambiguous Java methods found, using subscribe(java.util.Map)
RxJava => Could not find function language adaptor: Groovy with path: rx.lang.groovy.GroovyAdaptor
RxJava => Successfully loaded function language adaptor: JRuby with path: rx.lang.jruby.JRubyAdaptor
RxJava => Could not find function language adaptor: Clojure with path: rx.lang.clojure.ClojureAdaptor
RxJava => Could not find function language adaptor: Scala with path: rx.lang.scala.ScalaAdaptor
one
two

Which kind of works, but it's not as smooth as the ideal API would be:

observable.subscribe { |x| puts x }

But that would probably require a real JRuby native extension (if I get the time I'll send you a pull request with one).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions