Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8184320

Calling toString() on ListCell.itemProperty() gives StackOverflowError

XMLWordPrintable

    • x86_64
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_121"
      Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux XPS-15-9560 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      I call ListView.setCellFactory() and call ListCell.textProperty().bind() with a StringBinding. The StringBinding calls ListCell.itemProperty().toString(). Executing this code causes stack overflow

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the following example. Select a file from the FileChooser.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      See the selected file in the ListView.
      ACTUAL -
      StackOverflowError

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package listview.example;

      import java.io.File;
      import java.util.concurrent.Callable;

      import javafx.beans.binding.Bindings;
      import javafx.beans.binding.StringBinding;
      import javafx.beans.property.ObjectProperty;
      import javafx.event.ActionEvent;
      import javafx.event.EventHandler;
      import javafx.geometry.Insets;
      import javafx.geometry.Pos;
      import javafx.scene.control.Button;
      import javafx.scene.control.ContextMenu;
      import javafx.scene.control.Label;
      import javafx.scene.control.ListCell;
      import javafx.scene.control.ListView;
      import javafx.scene.control.MenuItem;
      import javafx.scene.control.Separator;
      import javafx.scene.layout.VBox;
      import javafx.stage.FileChooser;
      import javafx.stage.Stage;

      public class FileUploaderVBox extends VBox {

      ListView<File> filesToUpload = new ListView<>();

      public FileUploaderVBox(Stage primaryStage) {
      setAlignment(Pos.TOP_CENTER);

      Label l = new Label("Select Files to Upload");
      l.setStyle("-fx-font: 12 arial; -fx-font-weight: bold;");
      setMargin(l, new Insets(25,0,20,0));

      Separator horizSeparator1 = new Separator();
      horizSeparator1.prefWidthProperty().bind(widthProperty());


      filesToUpload.setCellFactory(lv -> {

                  ListCell<File> cell = new ListCell<>();

                  ContextMenu contextMenu = new ContextMenu();


                  MenuItem deleteItem = new MenuItem();
                  deleteItem.textProperty().bind(Bindings.format("Delete \"%s\"", cell.itemProperty()));
                  deleteItem.setOnAction(event -> filesToUpload.getItems().remove(cell.getItem()));

                  contextMenu.getItems().addAll(deleteItem);

      // cell.textProperty().bind(cell.itemProperty());
      // cell.textProperty().bind(cell.itemProperty().asString());
                  
                  ObjectProperty<File> itemProperty = cell.itemProperty();
      // StringBinding sb = Bindings.createStringBinding(new Callable<String>() {
      //
      // @Override
      // public String call() throws Exception {
      //
      // if (null == itemProperty.getValue())
      // return "";
      // else
      // return itemProperty.getValue().toString();
      // }
      //
      // }, itemProperty);
                  
                  StringBinding sb = Bindings.createStringBinding(new Callable<String>() {

      @Override
      public String call() throws Exception {

      if (null == itemProperty)
      return "";
      else
      return itemProperty.toString();
      }
                  
                  }, itemProperty);
                  cell.textProperty().bind(sb);

       
                  cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
                      if (isNowEmpty) {
                          cell.setContextMenu(null);
                      } else {
                          cell.setContextMenu(contextMenu);
                      }
                  });

                  return cell ;
              });

      Separator horizSeparator2 = new Separator();
      horizSeparator2.prefWidthProperty().bind(widthProperty());

      Button chooseFileButton = new Button("Choose File");

      chooseFileButton.setOnAction(new EventHandler<ActionEvent> () {

      @Override
      public void handle(ActionEvent event) {

      FileChooser fileChooser = new FileChooser();
      File f = fileChooser.showOpenDialog(primaryStage);
      if (null != f)
      filesToUpload.getItems().add(f);
      }
      });

      getChildren().addAll(l, horizSeparator1, filesToUpload, horizSeparator2, chooseFileButton);

      }

      }



      package listview.example.test;


      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.stage.Stage;
      import listview.example.FileUploaderVBox;

      public class FileUploaderVBoxTest extends Application {

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

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

      FileUploaderVBox up = new FileUploaderVBox(primaryStage);
              Scene scene = new Scene(up, 400.0, 200.0);
              primaryStage.setScene(scene);
              primaryStage.show();
      }
      }



      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The code works if you call ListCell.itemProperty().getValue().toString() instead of ListCell.itemProperty().toString(). That's the commented out code in the example.

      If you don't call getValue() you get stack overflow.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: