0

Whenever I try to repopulate elements in TableView from an Executor in another class I get the following error:

MainController Init prints main.getCurrentTime = 2017-07-31T22:31:37.969
*** MainController Initialized ***
**** createAndStartScheduler **** 
repeat every 2
Platform.isFxApplicationThread() = true
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at testpackage.MainController.populateTable(MainController.java:107)
    at testpackage.Refresh.lambda$null$0(Refresh.java:41)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    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:745)

MainController.java

Error at 107: nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));

  @FXML // fx:id="tableView"
  private TableView<Item> tableView; // Value injected by FXMLLoader

  @FXML // fx:id="statusCol"
  private TableColumn<Item, Boolean> statusCol; // Value injected by FXMLLoader

  @FXML // fx:id="dateCol"
  // USing string to display it because SimpleDateFormat.format returns a string
  private TableColumn<Item, String> dateCol; // Value injected by FXMLLoader

  @FXML // fx:id="nameCol"
  private TableColumn<Item, String> nameCol; // Value injected by FXMLLoader

  @FXML // fx:id="urlCol"
  private TableColumn<Item, Hyperlink> urlCol; // Value injected by FXMLLoader

  public void initialize() {
    GimmeTheFreeStuff gimmeTheFreeStuff = new GimmeTheFreeStuff();
    GetSetProps getSetProps = new GetSetProps();
    System.out.println(
        "MainController Init prints main.getCurrentTime = " + Main.getCurrentTime().toString());
    // testLink is called twice in the try
    try {
      Main.getStage()
          .setTitle("GimmeTheFreeStuff for " + gimmeTheFreeStuff.getTitle(getSetProps.getLink()));
      populateTable("");
    } catch (IOException e) {
      System.err.println("Unable to set the title OR Unable to populate table");
      e.printStackTrace();
    }
    System.out.println("*** MainController Initialized ***");
  }

public void populateTable(String temp) throws IOException {
    nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
    dateCol.setCellValueFactory(new PropertyValueFactory<>("date"));
    urlCol.setCellValueFactory(new PropertyValueFactory<>("urlLink"));
    statusCol.setCellValueFactory(new PropertyValueFactory<>("status"));
    ObservableList<Item> oList =     
    FXCollections.observableArrayList(parseItemList(temp));
    tableView.getItems().setAll(oList);
    success();
}

Refresh.java

Error at 41: mainController.populateTable("");

static void createAndStartScheduler() throws IOException {
    scheduler = Executors.newSingleThreadScheduledExecutor();
    System.out.println("**** createAndStartScheduler **** ");

    long delay = 2;

    scheduler.scheduleAtFixedRate(() -> Platform.runLater(() -> {
      MainController mainController = new MainController();
      System.out.println("repeat every " + delay);
      System.out.println("Platform.isFxApplicationThread() = " + Platform
          .isFxApplicationThread()); // returns True
      try {
        mainController.populateTable("");
      } catch (IOException e) {
        e.printStackTrace();
      }
    }), delay, delay, TimeUnit.SECONDS);
  }

Since its a NullPointerException that means that at Error 118, either the PropertyValueFactory "name" is null OR something is wrong with nameCol. Most of the answers I've read just involve using Platform.runLater. The closest question that is similar to mine, I think is: JavaFX: Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

I would assume I have to somehow re-initialize nameCol, dateCol, etc?

EDIT #2 (found solution):

Thanks to Scary Wombat simple suggestion of debugging, I added if (namCol == null) { System.out.print("nameCol is null"); return;} nameCol did turn out to be null b/c FXMLLoader initializes the UI elements of MainController.fxml, and creating a new instance of MainController.java doesn't do anything. So I just had to get the FXMLLoader instance of the controller from Main.java and use that to update my TableView.

Main.java

FXMLLoader loader = new FXMLLoader(getClass().getResource("MainUserInterface.fxml"));
Parent root = loader.load();

MainController controller = loader.getController();
Refresh refresh = new Refresh();
refresh.setObj(controller);

Refresh.java

private static MainController obj;

public static MainController getObj() { return obj;}
public static void setObj(MainController obj) { Refresh.obj = obj;}
// used getObj() to update tableview instead of creating new instance of MainController

Hope this helps someone else!

oxjoe
  • 1
  • 2
  • simple debugging will determine whether `nameCol` is null or not. You do not show any code regarding this `field` – Scary Wombat Aug 01 '17 at 02:19
  • I put a breakpoint at 107: nameCol.setCellValueFactory(new PropertyValueFactory<>("name")); And after it was done executing nameCol cellValueFactory wasn't null, I think it showed me the memory locations (ObjectProperty [bean: javafx.scene.control.TableColumn@25eb6158, name: cellValueFactory, value: javafx.scene.control.cell.PropertyValueFactory@23979fbf]) – oxjoe Aug 01 '17 at 02:40

0 Answers0