-1

I have a ComboBox with several items and, when clicking on one of those items, the application should load new items from database in the ComboBox.

I'm using a Platform.RunLater to first clear data of ComboBox using combobox.getItems().clear(); and then obtain data again from database and update the ComboBox.

The first time to load data from database in the ComboBox it works but when clicking the item in the ComboBox drop-down menu the application shows the following error:

  Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787)
at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670)
at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8863)
at javafx.controls/javafx.scene.control.skin.ComboBoxListViewSkin.lambda$new$7(ComboBoxListViewSkin.java:182)
at java.base/java.util.function.Consumer.lambda$andThen$0(Consumer.java:65)
at javafx.controls/com.sun.javafx.scene.control.LambdaMultiplePropertyChangeListenerHandler.lambda$new$1(LambdaMultiplePropertyChangeListenerHandler.java:49)
at javafx.base/javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.controls/javafx.scene.control.ComboBoxBase.setValue(ComboBoxBase.java:151)
at javafx.controls/javafx.scene.control.ComboBox.updateValue(ComboBox.java:520)
at javafx.controls/javafx.scene.control.ComboBox.access$200(ComboBox.java:194)
at javafx.controls/javafx.scene.control.ComboBox$3.changed(ComboBox.java:503)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
at javafx.base/javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113)
at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
at javafx.controls/javafx.scene.control.SelectionModel.setSelectedItem(SelectionModel.java:105)
at javafx.controls/javafx.scene.control.ComboBox$ComboBoxSelectionModel.lambda$new$0(ComboBox.java:560)
at javafx.base/com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:136)
at javafx.base/com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80)
at javafx.base/javafx.beans.property.ReadOnlyIntegerPropertyBase.fireValueChangedEvent(ReadOnlyIntegerPropertyBase.java:72)
at javafx.base/javafx.beans.property.ReadOnlyIntegerWrapper.fireValueChangedEvent(ReadOnlyIntegerWrapper.java:102)
at javafx.base/javafx.beans.property.IntegerPropertyBase.markInvalid(IntegerPropertyBase.java:114)
at javafx.base/javafx.beans.property.IntegerPropertyBase.set(IntegerPropertyBase.java:148)
at javafx.controls/javafx.scene.control.SelectionModel.setSelectedIndex(SelectionModel.java:69)
at javafx.controls/javafx.scene.control.ComboBox$ComboBoxSelectionModel$2.onChanged(ComboBox.java:591)
at javafx.base/javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at javafx.base/com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at javafx.base/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.base/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.base/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.base/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.base/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.base/com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:157)
at com.sener.dbgui.controller.ComponentController$1$1.run(ComponentController.java:289)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76)
at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83)
at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782)
... 64 more
Caused by: java.lang.NullPointerException
at com.sener.dbgui.controller.ComponentController.manufacturerAction(ComponentController.java:195)
... 75 more

I'm using the DataResult solution to this question to obtain the data from database. As the result for the query to database is a unique column I can obtain all the elements of column 0 from DataResult.

Part of the code in the fillComboBox() method called when initializing the view and again when clicking an item of the combobox:

...
//Load data into dataFromCommonDAO (DataResult Object)
dataFromCommonDAO = newCommonDAOImpl.getDataFromDB(inputsList);

//JavaFX main Thread
Platform.runLater(new Runnable() {

                        public void run() {
                            //First clear all items of ComboBox
                            cmbBox.getItems().clear();

                            cmbBox.setEditable(true);
                            cmbBox.setVisibleRowCount(10);

                            if (cmbBox == cmbManufacturer) {

                                cmbBox.getItems().add("NEW MANUFACTURER");

                            }

                            for (int i = 0; i < dataFromCommonDAO.getNumRows() ; i++ ) {
                                cmbBox.getItems().add(dataFromCommonDAO.getData(0,i).toString());
                            }

                            if (cmbBox == cmbManufacturer && sqlFile.equals("getManufNamesbyPN.txt") ) {
                                cmbBox.getItems().add("SHOW ALL...");
                            }
                        }
                    });

...

If I don't use the getItems().clear() the ComboBox will show the previous loaded data in addition to the new one obtained from database.

So, how can I proceed to refresh the ComboBox without this error?

LazyTurtle
  • 131
  • 1
  • 3
  • 16
  • It's probably better to use two `ComboBoxes`. – SedJ601 Feb 13 '18 at 19:47
  • The problem is that, using this idea, the user can click multiple times on the items so I should create one ComboBox per click. – LazyTurtle Feb 13 '18 at 19:58
  • 1
    Post the stack trace, and the actual code. Some of these vague snippets you have posted won't even compile. It's not clear which parts of the code are wrapped in the `Platform.runLater(..)` (**not** `Platform.RunLater(...)`), or even why you are using that at all. If you want help, please post a question that has some chance of being understandable. – James_D Feb 13 '18 at 20:08

1 Answers1

1

Ok, so I was having a problem in the Action where the app compares the selected item with other String. It was basically an error of String comparison between the ComboBox selected value and a fixed String value.

The code that was giving the error was:

    @FXML
    void manufacturerAction(ActionEvent event) {
        if (cmbManufacturer.getValue().equals("NEW MANUFACTURER")) {

            ...

        }else if (cmbManufacturer.getValue().equals("SHOW ALL...")) {
            //Here is where the update combobox method is called. 
            //It will reload manufacturer ComboBox with all manufacturer from table

            fillComboBox(cmbManufacturer, sqlFileNameManuf);

        }
    }
  ...

The corrected code:

    private String newManufacturer = "NEW MANUFACTURER";
    private String otherManufacturers = "SHOW ALL..";
    ...
    @FXML
    void manufacturerAction(ActionEvent event) {

        if ( newManufacturer.equals(cmbManufacturer.getValue())) {

            ...
        }else if (otherManufacturers.equals(cmbManufacturer.getValue() )) {

            fillComboBox(cmbManufacturer, sqlFileNameManuf);
        }
 ...

The question here then is why was it giving an error when I have basically only changed the order in the String comparison. Maybe this is because using the combobox item to compare using

ComboBox.getValue().equals("something") 

while updating it using Platform.runLater is not possible,

But I still don´t get it.

LazyTurtle
  • 131
  • 1
  • 3
  • 16
  • You should always check your stack trace when you get an exception. `Caused by: java.lang.NullPointerException at ComponentController.manufacturerAction(ComponentController.java:195)` pretty much tells you where and what the error was. In your case `getValue()` returned `null` which caused the error when you called `getValue().equals(...)`. By changing the order your `equals()` is no longer called on a `null` object. To prevent problems like this, you can use [Objects.equals(val1, val2)](https://docs.oracle.com/javase/7/docs/api/java/util/Objects.html) – Markus Köbele Feb 14 '18 at 16:05
  • Thank you for that tip. I will use the Object equals(val1,val2) to prevent this type of problems. – LazyTurtle Feb 14 '18 at 16:47