Details

    • Type: New Feature New Feature
    • Status: Closed Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: JRuby 1.4
    • Component/s: Java Integration
    • Labels:
      None
    • Number of attachments :
      2

      Description

      When calling methods in java from jruby where the same method has multiple signatures, it would be useful to have a way to pass a "typed" null object.

      For example if I have 2 methods in java:
      doSomething(Frame f, int i)
      doSomething(Component c, int i)

      and I want to make sure I call the second method but with a null component then in java I do this:
      obj.doSomething((Component)null, 0)

      But in jruby I haven't found a convinient way to do this. My current solution is to use reflection something like this:
      method = obj.java_class.declared_method(:doSomething, Component, int)
      method.invoke( obj, Java.primitive_to_java(nil), 0 )

      If instead there was something like a null method on wrapped java classes this would be much nicer:
      obj.doSomething(Component.null, 0)
      The null method could return an special object that the jruby Java method finding code could use to find the correct method in java.

      1. jruby-3865.patch
        4 kB
        Charles Oliver Nutter
      2. jruby-3865-jtg.patch
        5 kB
        Joshua Go

        Issue Links

          Activity

          Hide
          Charles Oliver Nutter added a comment -

          Ok, now this is a real need for sure, and one I've known we would hear about eventually.

          Your reflection workaround is clever, and probably the only way at the moment. It is obviously less than desirable.

          I think this bug may lead the way toward a practical casting syntax/API we can use for Java integration. I'm marking this a blocker for 1.4.

          Show
          Charles Oliver Nutter added a comment - Ok, now this is a real need for sure, and one I've known we would hear about eventually. Your reflection workaround is clever, and probably the only way at the moment. It is obviously less than desirable. I think this bug may lead the way toward a practical casting syntax/API we can use for Java integration. I'm marking this a blocker for 1.4.
          Hide
          Scott Cytacki added a comment -

          Another option would be to simplify the reflection approach which would then help other cases. Live Connect 3 has something like this:
          http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html (see the bottom of the page)

          perhaps this could look like:
          ObjClass.java_method(:doSomething, Component, :int).invoke(obj, nil, 0)

          If this is worth it then there could be some special method on the obj itself so this would be possible:
          obj.java_method(:doSomething, Component, :int).invoke(nil, 0)

          Show
          Scott Cytacki added a comment - Another option would be to simplify the reflection approach which would then help other cases. Live Connect 3 has something like this: http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html (see the bottom of the page) perhaps this could look like: ObjClass.java_method(:doSomething, Component, :int).invoke(obj, nil, 0) If this is worth it then there could be some special method on the obj itself so this would be possible: obj.java_method(:doSomething, Component, :int).invoke(nil, 0)
          Hide
          Charles Oliver Nutter added a comment -

          Scott: That's definitely planned, probably in the form of making the proxy classes (the Class object you get from e.g. java.lang.System-style accesses) provide a complete set of reflective capabilities. For the moment, most reflective logic you would need is available via the Java::JavaClass object you get from calling .java_class, which allows working around most things (in a very painful way).

          Show
          Charles Oliver Nutter added a comment - Scott: That's definitely planned, probably in the form of making the proxy classes (the Class object you get from e.g. java.lang.System-style accesses) provide a complete set of reflective capabilities. For the moment, most reflective logic you would need is available via the Java::JavaClass object you get from calling .java_class, which allows working around most things (in a very painful way).
          Hide
          Charles Oliver Nutter added a comment -

          I started to tackle this but it gets pretty involved; we don't have any logic at present for handling a normal JavaClass/JavaObject/proxy wrapping a null value, so we may want to introduce a new custom type that the method selection can recognize. I'm attaching what I have, which does allow typed null references for simple cases but blows up a bunch of tests and specs.

          Show
          Charles Oliver Nutter added a comment - I started to tackle this but it gets pretty involved; we don't have any logic at present for handling a normal JavaClass/JavaObject/proxy wrapping a null value, so we may want to introduce a new custom type that the method selection can recognize. I'm attaching what I have, which does allow typed null references for simple cases but blows up a bunch of tests and specs.
          Hide
          Thomas E Enebo added a comment -

          Not getting fixed for 1.4. java_method and java_send can be used to work around this problem for 1.4 too.

          Show
          Thomas E Enebo added a comment - Not getting fixed for 1.4. java_method and java_send can be used to work around this problem for 1.4 too.
          Hide
          Joshua Go added a comment - - edited

          Working off the patch that Charles submitted, I just tracked it down and ran the tests to see if I could find the cause of the problem.

          The problem was that the change in src/org/jruby/RubyBasicObject.java would cause more involved tests to fail: getMetaClass().dataGetStruct() was returning null.

          I've added a check which should preserve the behaviour of Charles's patch while not breaking any tests.

          Now, as for whether getMetaClass().dataGetStruct() should ever return null: this is probably better left to a grander effort tackling more general aims, if you guys would like to pursue it.

          Show
          Joshua Go added a comment - - edited Working off the patch that Charles submitted, I just tracked it down and ran the tests to see if I could find the cause of the problem. The problem was that the change in src/org/jruby/RubyBasicObject.java would cause more involved tests to fail: getMetaClass().dataGetStruct() was returning null. I've added a check which should preserve the behaviour of Charles's patch while not breaking any tests. Now, as for whether getMetaClass().dataGetStruct() should ever return null: this is probably better left to a grander effort tackling more general aims, if you guys would like to pursue it.
          Hide
          Charles Oliver Nutter added a comment -

          I think this is resolved.

          In JRuby 1.4 we added the ability call a specific overload of a method with any arguments. So using the bug's example:

          # given these methods in class Foo
          doSomething(Frame f, int i)
          doSomething(Component c, int i)
          
          # could be called using specific signatures using java_send
          obj.java_send(:doSomething, [Frame, Java::int], nil, 0)
          obj.java_send(:doSomething, [Component, Java::int], nil, 0)
          
          # retrieved as unique-overload methods
          obj.java_method(:doSomething, [Frame, Java::int]).call(nil, 0)
          obj.java_method(:doSomething, [Component, Java::int]).call(nil, 0)
          
          # or aliased to specific names
          class Foo
            java_alias :doSomethingFrame, :doSomething, [Frame, Java::int]
            java_alias :doSomethingComponent, :doSomething, [Component, Java::int]
          end
          
          Show
          Charles Oliver Nutter added a comment - I think this is resolved. In JRuby 1.4 we added the ability call a specific overload of a method with any arguments. So using the bug's example: # given these methods in class Foo doSomething(Frame f, int i) doSomething(Component c, int i) # could be called using specific signatures using java_send obj.java_send(:doSomething, [Frame, Java::int], nil, 0) obj.java_send(:doSomething, [Component, Java::int], nil, 0) # retrieved as unique-overload methods obj.java_method(:doSomething, [Frame, Java::int]).call(nil, 0) obj.java_method(:doSomething, [Component, Java::int]).call(nil, 0) # or aliased to specific names class Foo java_alias :doSomethingFrame, :doSomething, [Frame, Java::int] java_alias :doSomethingComponent, :doSomething, [Component, Java::int] end

            People

            • Assignee:
              Charles Oliver Nutter
              Reporter:
              Scott Cytacki
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: