New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Concrete JRuby Implementations of Abstract Java Classes Can't be Constructed With Reflection #5270
Comments
I don't know whether it is any help to you but I've used abstract classes in JRubyArt/propane and this works for me https://ruby-processing.github.io/propane/classes/library_proxy |
Ok the usual way we improve these features is by getting some new specs in place. Class extension has needed an overhaul for years but the specs are very weak. Can you folks collab to figure out both what we do now and what we want to do? The new impl is not terribly hard if we have good specs and can throw away the current impl. |
OK just to clarify works for me as expected, but package monkstone.reflect;
public abstract class SimpleAbstract {
public abstract void javaMethod();
} require 'java'
require '/home/tux/reflect/reflect/target/reflect-1.0-SNAPSHOT.jar'
class SimpleRubyClass < Java::MonkstoneReflect::SimpleAbstract
def java_method
puts 'java_method from ruby'
end
end
reflect = SimpleRubyClass.new
reflect.java_method Now definitely that's just too simple for a test case, but put together with my real world example that does involve java reflection I think that current impl does work, but perhaps not as ScottHanley wants. |
@monkstone - If I am looking over the examples that you provided it seems like you are focusing more on overriding an abstract method from a Java class in a Jruby class. That situation seems to work fine for me in testing as well. I am concerned with the The issue does look like a bug, because if I call @headius - I don't mind putting some effort towards it. From looking at the code it seems like the current spec is jruby/spec/java_integration/types/extension_spec.rb. Are there more specs that would need to be updated as well or just this one? |
@ScottHaney So long as my use case keeps working I'm happy. I create a custom abstract class, with the sole purpose to to gain access (in ruby) to java methods (on processing PApplet class) that have a reflective access via java. I only posted just in case you had a similar problem. As far as I knew the use case for the reflective constructor in jruby is to cope with different java class constructor signatures. |
So I'm back to work after some vacation...and I think what you are asking for here is that the Java-facing concrete class have a no-argument constructor, yes? It's not impossible to do (and maybe not difficult) but this is the sort of thing we want to get right once. Currently the concrete class created does not have an easily-usable constructor. This logic was written many years ago and we have resisted rewriting it due to its complexity. I believe the current logic would allow you to construct the object via a more complex constructor signature, perhaps one that takes the JRuby "Ruby" runtime object and the RubyClass object associated with the new class, but that may not be convenient for what you are doing... |
@headius I believe that you have it right. The java facing class of the class that I create in ruby code needs to have a default constructor in order for the third party java code that I am interacting with to work. To make sure that I understand the scope right the spec that would be affected by the changes would be jruby/spec/java_integration/types/extension_spec.rb correct? I am new to the code base and haven't looked through it a lot, but from glancing, the code files that look like they have code related to this issue are: core/src/main/java/org/jruby/RubyClass.java Is this the right area? Also if you could give more specific details on the scope of the changes that you are looking for I could get a better idea of what to include in the updated spec. As far as the workaround you mentioned at the end of your last post, unfortunately the creation of the object is deep inside a third party Java library. So I can't change it to use the workaround that you suggested unfortunately. |
@headius I spent some time looking over the source code and I think I have a better understanding of your recommendation to use the JRuby "Ruby" runtime object. I tried the following:
This creates a java object that has the methods that I need on it and also inherits from the java class that I want it to, however, the proxy constructor has an extra argument of type I also found the Alternatively I could add another constructor if it were possible, I did see an |
Fixed by #6422 |
Environment
Expected Behavior
Creating a JRuby class from an abstract Java class should have a constructor that can be called through reflection. This means that the following code should work
JRubyConcreteClass.java_class.constructor.new_instance
whenJRubyConcreteClass
derives from an abstract Java class.Actual Behavior
It complains that it can't instantiate the concrete class because it can't make an instance of the abstract base class. The error says "TypeError: can't make instance of AbstractClass". I have created a repository that reproduces the issue. Also overriding abstract java methods in JRuby doesn't seem to work either which is something that would be helpful to have.
Potential Work Around for now
As a work around I am going to create concrete derived classes that directly implement the abstract methods and then add new setter type methods that JRuby code can then call to set data on. The data populated through these setters will then be used inside of the overridden abstract methods to get the desired behavior. This is a hack, but I think it will work for now.
I am also open to helping out with some development depending on what might be involved in fixing improving the behavior of implementations of abstract Java classes.
Thank you for your time and help!
The text was updated successfully, but these errors were encountered: