JDK-8151087 : Editable ComboBox CCE
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 8u74
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2016-03-02
  • Updated: 2016-09-20
  • Resolved: 2016-03-03
Related Reports
Relates :  
Description
Seems to be a regression possibly introduced with 8u72. The exception is thrown on focus lost and if type is not String and a valueProperty listener is installed just like in the example below. The issue does not occur with 8u73.

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.stage.Stage;

public class ComboBoxCCE extends Application {

    private Parent getContent() {
        ComboBox<Pos> combo = new ComboBox<>();
        combo.setItems(FXCollections.observableArrayList(Pos.TOP_LEFT, Pos.TOP_CENTER, Pos.TOP_RIGHT, Pos.CENTER_LEFT, Pos.CENTER, Pos.CENTER_RIGHT, Pos.BOTTOM_LEFT, Pos.BOTTOM_CENTER, Pos.BOTTOM_RIGHT));
        combo.setValue(null);
        combo.valueProperty().addListener((o, ov, nv) -> {
            System.err.println("--- New Value: " + nv);
        });
        combo.setEditable(true);
        return combo;
    } 
     
    @Override 
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setScene(new Scene(getContent()));
        primaryStage.show(); 
    } 

    public static void main(String[] args) { 
        launch(args); 
    } 
} 

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: java.lang.String cannot be cast to javafx.geometry.Pos
        at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(Unknown Source)
        at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
        at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(Unknown Source)
        at javafx.beans.property.ObjectPropertyBase.markInvalid(Unknown Source)
        at javafx.beans.property.ObjectPropertyBase.set(Unknown Source)
        at javafx.scene.control.ComboBoxBase.setValue(Unknown Source)
        at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.setTextFromTextFieldIntoComboBoxValue(Unknown Source)
        at com.sun.javafx.scene.control.skin.ComboBoxPopupControl.lambda$new$291(Unknown Source)
        at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(Unknown Source)
        at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
        at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(Unknown Source)
        at javafx.scene.Node$FocusedProperty.notifyListeners(Unknown Source)
        at javafx.scene.Scene$13.invalidated(Unknown Source)
        at javafx.beans.property.ObjectPropertyBase.markInvalid(Unknown Source)
        at javafx.beans.property.ObjectPropertyBase.set(Unknown Source)
        at javafx.scene.Scene$KeyHandler.setFocusOwner(Unknown Source)
        at javafx.scene.Scene$KeyHandler.requestFocus(Unknown Source)
        at javafx.scene.Scene$KeyHandler.access$1900(Unknown Source)
        at javafx.scene.Scene.requestFocus(Unknown Source)
        at javafx.scene.Node.requestFocus(Unknown Source)
        at com.sun.javafx.scene.control.behavior.TextAreaBehavior.mousePressed(Unknown Source)
        at com.sun.javafx.scene.control.skin.TextAreaSkin$ContentView.lambda$new$225(Unknown Source)
        at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
        at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
        at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
        at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
        at javafx.event.Event.fireEvent(Unknown Source)
        at javafx.scene.Scene$MouseHandler.process(Unknown Source)
        at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
        at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(Unknown Source)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
        at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
        at com.sun.glass.ui.View.notifyMouse(Unknown Source)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Comments
I think this issue can be closed - created a new one for the mentioned behavior. https://bugs.openjdk.java.net/browse/JDK-8151129
03-03-2016

True, stumbled across the issue while investigating another issue. With 8u72 an edited value is set on focus lost - unfortunately in this case a user can't install a focus listener to track the value. The user installed focus listener is called before the value is set. One would argue to observe the valueProperty instead. However, for some scenarios it's required that the value is committed before all listeners get notified - i. e. if value validation is triggered on focus lost by such a listener.
02-03-2016

I would probably therefore argue that this isn't a regression or an issue - it is simply a requirement to use the converter API when you have an editable ComboBox with a non-String data type.
02-03-2016

I should note that the CCE will happen in other cases, e.g. when the ENTER key is pressed after selecting an item. In both cases, this can be resolved by providing a StringConverter to convert the TextField string into a Pos object: combo.setConverter(new StringConverter<Pos>() { @Override public String toString(Pos pos) { return pos == null ? "" : pos.toString(); } @Override public Pos fromString(String string) { return Pos.valueOf(string); } });
02-03-2016

Appears to be regression due to JDK-8136838.
02-03-2016