1

My JavaFx app throwing an exception and does not point towards a single line of my own code. What does this mean?

It is confusing me because I encountered it a few times now without being able to reproduce. Once at booting, once at being idle (minimized) and returning back to the app, once at being idle (but still shown on screen) and returning back to the app.

The full code is too long, I can post little snippets that operate in the configuration. And some links to the complete app to get an overview what Im trying to make.

enter image description here

https://www.youtube.com/watch?v=Oev1IJZvAPw

https://github.com/JoostMeulenkamp/VPL

Snippet 1 (calculate function of a node that adds an item to the end of a list):

@Override
public void calculate() {

    //Get incoming data
    Object raw = inPorts.get(0).getData();
    Object item = inPorts.get(1).getData();

    //Finish calculate if there is no incoming data
    if (raw == null) {
        return;
    }

    //Check if all incoming data is in the correct format
    boolean hasError = false;
    if (!(raw instanceof List)) {
        System.out.println("This is not a list");
        hasError = true;
    }
    if (item instanceof List) {
        System.out.println("Just one item can be added at a time");
        hasError = true;
    }
    if (inPorts.get(1).connectedConnections.size() > 0
            && inPorts.get(0).connectedConnections.size() > 0) {
        Class listDataType = inPorts.get(0).connectedConnections.get(0).getStartPort().dataType;
        Class itemDataType = inPorts.get(1).connectedConnections.get(0).getStartPort().dataType;
        if (itemDataType.isAssignableFrom(listDataType)) {
            System.out.println("Element is not of same type as the list's");
            hasError = true;
        }
    }
    if (hasError) {
        return;
    }

    //Add item to end
    List source = (List) raw;

    //Create a new list when autoCheckBox is checked, otherwise add to existing 
    //HACK new list is created that is identical because otherwise data is not forwarded
    //When isClicked, check changes to empty circle
    if (this.autoCheckBox.isClicked()) {
        source.add(item);
        List target = new ArrayList();
        target.addAll(source);

        //Set outgoing data
        outPorts.get(0).setData(target);

    } else {
        List target = new ArrayList();
        target.addAll(source);
        target.add(item);

        //Set outgoing data
        outPorts.get(0).setData(target);
    }

}

Snippet 2 Calculate function of a node that outputs lists to a textfield.

    @Override
    public void calculate() {
        //Get controls and data
        TextArea area = (TextArea) controls.get(0);
        Object data = inPorts.get(0).getData();
        area.setText("");

        //Do Action
        if (inPorts.get(0).getData() != null && inPorts.get(0).connectedConnections.size() > 0) {
            //Set data type corresponding to source
            outPorts.get(0).dataType = inPorts.get(0).connectedConnections.get(0).getStartPort().dataType;
            outPorts.get(0).setName(inPorts.get(0).connectedConnections.get(0).getStartPort().getName());
            if (data instanceof List) {
                List list = (List) data;

                for (Object object : list) {
                    if (object == null) {
                        area.appendText("null");
                    } else {
                        area.appendText(object.toString() + "\n");
                    }
                }
            } else {
                area.setText(data.toString());
            }
        } else {
            //Set data type back to string
            outPorts.get(0).dataType = String.class;
            outPorts.get(0).setName("String");
            if (inPorts.get(0).isActive()) {
                area.setText("null");
            } else {
                area.setText("");
            }
        }

        //Set Data
        outPorts.get(0).setData(data);

//        System.out.println(outPorts.get(0).dataType);
    }

This exception stacktrace keeps repeating itself:

    Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.elementData(ArrayList.java:418)
    at java.util.ArrayList.get(ArrayList.java:431)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1591)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.layout.Region.impl_computeGeomBounds(Region.java:3078)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3559)
    at javafx.scene.Node.getLocalBounds(Node.java:3480)
    at javafx.scene.Node.updateTxBounds(Node.java:3643)
    at javafx.scene.Node.getTransformedBounds(Node.java:3426)
    at javafx.scene.Parent.getChildTransformedBounds(Parent.java:1732)
    at javafx.scene.Parent.updateCachedBounds(Parent.java:1596)
    at javafx.scene.Parent.recomputeBounds(Parent.java:1535)
    at javafx.scene.Parent.impl_computeGeomBounds(Parent.java:1388)
    at javafx.scene.Node.updateGeomBounds(Node.java:3579)
    at javafx.scene.Node.getGeomBounds(Node.java:3532)
    at javafx.scene.Node.impl_computeLayoutBounds(Node.java:3376)
    at javafx.scene.Group.impl_computeLayoutBounds(Group.java:165)
    at javafx.scene.Node$12.computeBounds(Node.java:3225)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9308)
    at javafx.scene.Node$LazyBoundsProperty.get(Node.java:9278)
    at javafx.scene.Node.getLayoutBounds(Node.java:3240)
    at javafx.scene.layout.AnchorPane.layoutChildren(AnchorPane.java:328)
    at javafx.scene.Parent.layout(Parent.java:1087)
    at javafx.scene.Scene.doLayoutPass(Scene.java:552)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)
Josephus87
  • 1,126
  • 9
  • 19
  • 1
    You are obviously trying to access an item of an ArrayList at the index - 1, which cannot exist... Do you have any ArrayList in your code? Post some code please... – deHaar Jul 21 '17 at 12:48
  • Sounds like a common bug with ComboBoxes: https://stackoverflow.com/questions/39712765/javafx-8-filtered-combobox-throws-indexoutofboundsexception-when-popup-clicked – user11153 Jul 21 '17 at 13:04
  • 2
    What thread is the `calculate()` method called on? These kinds of errors can arise in some circumstances if you try to update UI elements from a background thread. – James_D Jul 21 '17 at 13:19
  • Calculate is called on the main javafx thread from all nodes. Also the Timer/Interval Node. it creates a seperate thread that has a boolean property that changes every 5 mins. a listener in the main thread responds on the change and calls calculate – Josephus87 Jul 21 '17 at 13:23
  • I had "TextField nodes" (snippet 2) after the "accumulatively add item to list node" (snippet 1). I removed them and I havent had an exception for the last few hours. But this could be just a fluke(?). hints where my problems could originate from are helpful! – Josephus87 Jul 21 '17 at 13:27
  • 2
    If you have a listener responding to the change in a property, the listener will be invoked on the same thread that changes the value of the property. So if that property change is occurring on a background thread (i.e. not the FX Application Thread), any changes to the UI in the listener must be wrapped in a call to `Platform.runLater(...)`. You can use [`Platform.isFxApplicationThread()`](http://docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#isFxApplicationThread--) to do some diagnostics to see if your listener is being invoked on a background thread if you need. – James_D Jul 21 '17 at 13:50
  • @James_D you were correct, calculate() was not called by the FX thread. Every UI changing method is now called from the FX thread by Platform.runLater(). – Josephus87 Jul 25 '17 at 05:31

1 Answers1

1

As James_D stated:

These kinds of errors can arise in some circumstances if you try to update UI elements from a background thread.

Every UI changing method is now called from the FX thread by Platform.runLater().

Josephus87
  • 1,126
  • 9
  • 19