I'm attempting to extend a concrete Java class (TableCell from javafx libs) in JavaScript, then call a method on the superclass. I have no problem doing this with the Rhino engine, but it's failing on Nashorn. My code is:
var Cell = Java.extend(fx.TableCell);
var cell = new Cell() {
updateItem: function (item, isEmpty) {
if(!isEmpty){
cell.super$setText(item);
}
}
};
return cell;
In addition to the "super$setText" syntax above, which was added to nashorn back in August, I have tried the Java.super
call as mentioned in Accessing Methods of a Superclass in the nashorn guide:
var Cell = Java.extend(fx.TableCell);
var cell = new Cell() {
updateItem: function (item, isEmpty) {
if(!isEmpty){
Java.super(cell).setText(item);
}
}
};
return cell;
These snippets both fail when the corresponding table view is being populated. cell.super$setText
throws 'null' has no such function "super$setText"
which strikes me as odd, as I've pasted the entire contents of the method - there should be no way the closed-over cell
variable becomes null. Java.super(cell).setText
throws "cannot call undefined."
I've also tried the convenient property syntax cell.text = item
which appears to set a new javascript field without complaining, but does nothing to display the text in the table view.
My JDK8 build is quite recent
C:\> java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b124)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b66, mixed mode)
I'm having trouble discerning if this is a nashorn bug, or a problem with my source. Is this the correct syntax? I'm also wondering if it matters that setText
is not defined on TableCell
, but one of its superclasses. Is nashorn only able to traverse one level up the hierarchy?
Welp, this all started because my table was showing all my TableCells without any text. I still have that problem, but I have eliminated the superclass method call issue.
I made a Java class to place all required methods directly in the superclass, and used this from my JavaScript. The class source is as follows:
public class JsTextTableCell<S,T> extends javafx.scene.control.TableCell<S, T> {
public void setText(Object text){
System.out.println("In java, calling setText(" + text.toString() + ")");
super.setText(text.toString());
}
}
Then I changed my javascript to:
fx.EditableTextTableCell = function () {
var cell;
if(!fx.EditableTextTableCell.Class) {
fx.EditableTextTableCell.Class = Java.extend(fx.JsTextTableCell, {
updateItem: function (item, isEmpty) {
if(!isEmpty){
cell.super$setText(item);
}
}
});
}
cell = new fx.EditableTextTableCell.Class();
return cell;
};
This code runs just fine. In fact, both the Java.super
and cell.super$setText
methods work. My table still refuses to show my text, but that is another issue entirely. So it appears Nashorn indeed only travels one level up in searching for super class methods, and does not find methods inherited from further up in the inheritance chain.
Seems I was getting a sloppy in my frustration. In my solution above, I'm creating my new extended class only once, and am there after setting the text on the cell it closed over on the first invocation of the fx.EditableTableCell constructor. This ends up leaving all the cells in my table blank. The reason this happened is that you may not use this.text = item
within the updateItem function definition. You must have an external reference to the object, for whatever reason, and this caused me to leak the cell
variable and end up with a closure issue.
To recap : Java.super
and obj.super$methodName
are both fine ways to access a method defined directly on the superclass of a JavaAdapter in Nashorn, and nobody has ever really mastered closures.