Question

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?

Was it helpful?

Solution

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.

EDIT

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top