JDK-8144501 : TreeTableView's selectedItems reports include null items.
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 8u66
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2015-11-26
  • Updated: 2016-08-23
  • Resolved: 2016-01-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u112Fixed 9Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b18)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
TreeTableView's selectedItems reports include null items if deselect one item with "Ctrl".

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Steps to reproduce:

1. Run the below example.
2. Press "Ctrl"
3. Click on "Item 2"

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Method javafx.collections.ListChangeListener.Change.getList() must return selected items.
ACTUAL -
Method javafx.collections.ListChangeListener.Change.getList() returned list with null item:

Console:
1 > [null]
2 > [TreeItem [ value: Item 3 ]]

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class Main extends Application {

	@Override
	public void start(Stage primaryStage) throws Exception {

		TreeTableView<String> treeTable = new TreeTableView<>(new TreeItem<String>("Root"));
		treeTable.getRoot().setExpanded(true);
		treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 1"));
		treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 2"));
		treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 3"));
		treeTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
		treeTable.getSelectionModel().select(2);
		treeTable.getSelectionModel().select(3);

		TreeTableColumn<String, String> column = new TreeTableColumn<>("Text");
		column.setPrefWidth(150);
		column.setCellValueFactory(
				(CellDataFeatures<String, String> p) -> new ReadOnlyStringWrapper(p.getValue().getValue()));
		treeTable.getColumns().add(column);
		
		treeTable.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<TreeItem<String>>() {

			@Override
			public void onChanged(javafx.collections.ListChangeListener.Change<? extends TreeItem<String>> change) {

				System.out.println("1 > " + change.getList());
				System.out.println("2 > " + change.getList());
			}

		});
		
		primaryStage.setScene(new Scene(new VBox(treeTable)));
		primaryStage.show();
	}

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


Comments
Thanks.
18-05-2016

Backport pushed: http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/45f42124f7b4
15-05-2016

+1 Approved to backport to 8u-dev (8u112)
14-05-2016

Webrev for review is now available: http://cr.openjdk.java.net/~jgiles/8144501/
12-05-2016

Thank you for the additional information. Since this is a regression introduced in a recent JDK update release we will give serious consideration to a backport. I note that if we are able to safely backport a fix it would be available in 8u112, which is the October 2016 quarterly release.
12-05-2016

Since I am seeing the problem described by the above testprogram in our product I would much like to have a fix in the next JDK release (if that is possible at all). Whether this should be "only" the backport of the fix above or a a new fix I cannot tell.
12-05-2016

The linked fix can be applied (with some manual coercion) to the 8u-dev repo, and it does fix the problem for TreeTableView as shown in the test app above. However, when I apply the parameterised tests that I wrote in 9 into 8u-dev, I see that the tests still fail for ListView and TreeView. The question for now is: do we apply the fix to resolve the regression in TreeTableView as-is (and disable the tests), or do I spend more time trying to resolve the issue for ListView and TreeView also. It would almost certainly be quicker to simply create a new fix for 8u-dev than it would be to find the precise changeset that fixes the issue in list / tree (because there have been so many improvements in this code in JDK 9), but it may take some time (it's really hard to estimate these kinds of fixes given the large number of unit tests and the ease of breaking some of them).
11-05-2016

Here is a very small test program that will reproduce the Bug: import javafx.application.Application; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableView; import javafx.scene.control.TableView.TableViewSelectionModel; import javafx.stage.Stage; public class GetSelectedItemsBug extends Application { ObservableList<String> items = FXCollections.observableArrayList(); TableView<String> table = new TableView<>(); @Override public void start(Stage primaryStage) throws Exception { table.setItems(items); addPersons(); TableViewSelectionModel<String> model = table.getSelectionModel(); model.setSelectionMode(SelectionMode.MULTIPLE); model.select(1); model.select(2); model.clearSelection(1); System.out.println(model.getSelectedItems().get(0)); Platform.exit(); } private void addPersons() { items.add("Bilbo"); items.add("Frodo"); items.add("Merry"); } public static void main(String[] args) { launch(args); } } Output: jdk1.8.0_51: Merry (correct) jdk1.8.0_60: null (wrong) ... jdk1.8.0_91: null (wrong)
11-05-2016

Marking as a regression, since this bug was introduced in 8u60.
11-05-2016

Changeset: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/9b7e677b5314
12-01-2016

I've improved the test code slightly below: import javafx.application.Application; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.collections.ListChangeListener; import javafx.scene.Scene; import javafx.scene.control.SelectionMode; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableView; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception { TreeTableView<String> treeTable = new TreeTableView<>(new TreeItem<>("Root")); treeTable.getRoot().setExpanded(true); treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 1")); treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 2")); treeTable.getRoot().getChildren().add(new TreeItem<String>("Item 3")); treeTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); treeTable.getSelectionModel().select(2); treeTable.getSelectionModel().select(3); TreeTableColumn<String, String> column = new TreeTableColumn<>("Text"); column.setPrefWidth(150); column.setCellValueFactory( (TreeTableColumn.CellDataFeatures<String, String> p) -> new ReadOnlyStringWrapper(p.getValue().getValue())); treeTable.getColumns().add(column); treeTable.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<TreeItem<String>>() { @Override public void onChanged(javafx.collections.ListChangeListener.Change<? extends TreeItem<String>> change) { while (change.next()) { System.out.println("was removed: " + change.wasRemoved()); System.out.println("\tRemoved elements: " + change.getRemoved()); System.out.println("was added: " + change.wasAdded()); System.out.println("\tAdded elements: " + change.getAddedSubList()); System.out.println("Remaining elements in list " + change.getList()); } } }); primaryStage.setScene(new Scene(new VBox(treeTable))); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
06-12-2015