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

FXML DataBinding not working correctly

    XMLWordPrintable

Details

    • Bug
    • Status: Resolved
    • P4
    • Resolution: Fixed
    • 8
    • 8
    • javafx
    • None

    Description

      [PS: I am not sure I picked the correct "Affected Version" for this issue, the affected version is the one currently shipped with Java 8.0 EAP ( JavaFX Version 8.0.0-ea-b71 )]

      in JavaFX 2.x versions it was possible to bind data in FXML declarations like this:

                  <Label text="${corporation.employee.firstName}" />

      with employee being a SimpleObjectProperty and firstName being a StringProperty.

      I tried the Java 8 EAP today and got the following error:

      java.lang.NullPointerException
        at com.sun.javafx.fxml.BeanAdapter.<init>(BeanAdapter.java:77)
        at com.sun.javafx.fxml.expression.ExpressionValue$KeyPathMonitor.monitor(ExpressionValue.java:108)
        at com.sun.javafx.fxml.expression.ExpressionValue$KeyPathMonitor.monitor(ExpressionValue.java:121)
        at com.sun.javafx.fxml.expression.ExpressionValue$KeyPathMonitor.monitor(ExpressionValue.java:121)
        at com.sun.javafx.fxml.expression.ExpressionValue.monitorArguments(ExpressionValue.java:235)
        at com.sun.javafx.fxml.expression.ExpressionValue.addListener(ExpressionValue.java:196)
        at javafx.beans.property.StringPropertyBase.bind(StringPropertyBase.java:166)
        at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:382)
        at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:223)
        at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:576)
        at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2449)
        at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2149)
      ...

      I believe this is due the properties get() method is returning null at the time the application is started (at this time no employee is selected). This also happens if something is directly bound to the property which returns null:

      ${corporation.employee}

      Here is a testcase that shows the issue (attachments seems to be disabled?):

      Main.fxml: ====================

      <?xml version="1.0" encoding="utf-8"?>

      <?import java.lang.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      <?import javafx.scene.text.*?>
      <?import test.Corporation?>
      <?import test.Employee?>

      <VBox xmlns:fx="http://javafx.com/fxml"
                  fx:controller="test.MainController"
                  fx:id="root">
          <fx:define>
              <Corporation fx:id="corporation"/>
          </fx:define>
          <children>
              <Label text="${corporation.employee.firstName}"/>
              <Button fx:id="button1" text="John Doe" onAction="#setJohnDoe"/>
              <Button fx:id="button2" text="Carl Gustav" onAction="#setCarlGustav"/>
          </children>
      </VBox>

      MainController.java =================

      package test;

      import javafx.scene.control.Button;
      import javafx.scene.layout.VBox;

      public class MainController {

        public VBox root;

        public Button button1;
        public Button button2;

        public Employee johndoe = new Employee("John Doe");
        public Employee carlgustav = new Employee("Carl Gustav");

        public Corporation corporation;

        public void setJohnDoe(){
          corporation.setEmployee(johndoe);
        }
        public void setCarlGustav(){
          corporation.setEmployee(carlgustav);
        }
      }

      MainApplication.java ==============

      package test;

      import javafx.application.Application;
      import javafx.fxml.FXMLLoader;
      import javafx.scene.Scene;
      import javafx.scene.layout.Pane;
      import javafx.stage.Stage;

      public class MainApplication extends Application {


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

        @Override
        public void start(Stage stage) throws Exception {
          FXMLLoader loader = new FXMLLoader();
          loader.setLocation(getClass().getResource("Main.fxml"));
          Scene scene = new Scene((Pane)loader.load(), 600, 600);
          stage.setTitle("Bug Demonstration");
          stage.setScene(scene);
          stage.show();
        }
      }

      Corporation.java ==============

      package test;

      import javafx.beans.property.ObjectProperty;
      import javafx.beans.property.SimpleObjectProperty;

      public class Corporation {

        private ObjectProperty<Employee> employee = new SimpleObjectProperty<>();

        public ObjectProperty<Employee> employeeProperty(){
          return employee;
        }
        public final Employee getEmployee() {
          return employeeProperty().get();
        }
        public final void setEmployee( Employee value ) {
            employeeProperty().set(value);
        }
      }


      Employee.java ==============

      package test;

      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;

      public class Employee {

        private StringProperty firstName = new SimpleStringProperty("");

        public Employee(String s) {
          setFirstName(s);
        }

        public final StringProperty firstNameProperty(){
          return firstName;
        }

        public final String getFirstName() {
          return firstName.get();
        }

        public final void setFirstName( String value ) {
          firstName.set(value);
        }

      }






      Attachments

        Activity

          People

            mkubec Milan Kubec
            srheinnecjfx Sebastian Rheinnecker (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported: