This discussion is archived
7 Replies Latest reply: Jan 26, 2013 7:27 AM by James_D RSS

Invalid property. I cant understend what is the reason for this Exception!

idle Newbie
Currently Being Moderated
Hello everyone,
i try to load data in my TableView but i get this exception :
Invalid property.
file:/D:/Users/idle/Documents/Warehouse/dist/run661408274/Warehouse.jar!/org/warehouse/fxml/windows/SalesWindow.fxml:32
file:/D:/Users/idle/Documents/Warehouse/dist/run661408274/Warehouse.jar!/org/warehouse/fxml/windows/MainWindow.fxml:14
  at javafx.fxml.FXMLLoader$PropertyElement.<init>(FXMLLoader.java:1154)
  at javafx.fxml.FXMLLoader.createElement(FXMLLoader.java:2338)
  at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2311)
  at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2131)
  at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2028) 
...............................................................
Here is my code :
My property:

public class ItemProperty<Items> {

    private final SimpleStringProperty id;
    private final SimpleStringProperty name;
    private final SimpleStringProperty price;
    private final SimpleStringProperty quantity;
    private Items item;

    public ItemProperty(String id, String fName, String price, String q, Items i) {
        this.id = new SimpleStringProperty(id);
        this.name = new SimpleStringProperty(fName);
        this.price = new SimpleStringProperty(price);
        this.quantity = new SimpleStringProperty(q);
        this.item = i;
    }

    public String getName() {
        return name.get();
    }

     public SimpleStringProperty getNameProperty() {
         return name;
     }
    public void setName(String fName) {
        name.set(fName);
    }

    public String getPrice() {
        return price.get();
    }

    public void setPrice(String price) {
        this.price.set(price);
    }

    public SimpleStringProperty getPriceProperty() {
        return price;
    }

    public SimpleStringProperty getQuantityProperty() {
        return quantity;
    }
     
    public String getQuantity() {
        return quantity.get();
    }

    public void setQuantity(String quantity) {
        this.quantity.set(quantity);
    }

    public SimpleStringProperty getIdProperty() {
        return id;
    }

    public String getId() {
        return id.get();
    }

    public void setId(String code) {
        id.set(code);
    }

    public Items getItem() {
        return item;
    }
}
Controller for my FXML presentation
public class SalesWindow implements Initializable {
    
    @FXML
    private TableView<ItemProperty<Items>> itemsTable;
    @FXML
    private TableColumn<ItemProperty<Items>, String> idColumn;
    @FXML
    private TableColumn<ItemProperty<Items>, String> nameColumn;
    @FXML
    private TableColumn<ItemProperty<Items>, String> priceColumn;
    @FXML
    private TableColumn<ItemProperty<Items>, String> quantityColumn;

    final ObservableList<ItemProperty<Items>> itemList = FXCollections.observableArrayList();
    
    final ExecutorService executorService = Executors.newCachedThreadPool(); 
    
     public Task<Items> retrieveDBItems(){
        return new Task() {

            @Override
            protected Object call() throws Exception {
                List<Items> items = FXCollections.observableArrayList();
                items.addAll(new ItemsJpaController(DBconnect.getEntityManagerFactory()).findItemsEntities());              
                for(Items i : items){
                    itemList.add(new ItemProperty<>(String.valueOf(i.getItemsPK().getId())
                            , i.getName(), String.valueOf(i.getPrice()), String.valueOf(i.getQuantity()), i));
                }
                return null;
            }
        };
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        executorService.submit(this.retrieveDBItems());
        itemsTable.setItems(itemList);
    }
    
}
And that is the SalesWindow.fxml
<Group fx:id="salesWindow" xmlns:fx="http://javafx.com/fxml" fx:controller="org.warehouse.fxml.windows.controllers.SalesWindow">
  <children>
    <VBox>
      <TilePane fx:id="tilePane" hgap="-32.0" maxHeight="-Infinity" prefColumns="2" tileAlignment="TOP_LEFT" vgap="10.0" VBox.vgrow="ALWAYS">
        <children>
          <TextField fx:id="partnerField" alignment="CENTER" minHeight="30.0" minWidth="400.0" promptText="Add your Partner here" />
          <Button fx:id="partnerButton" alignment="CENTER" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
          <TextField fx:id="storeField" minHeight="30.0" minWidth="400.0" promptText="Add a Store here ..." />
          <Button fx:id="storeButton" alignment="CENTER" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
          <TextField fx:id="userField" minHeight="30.0" minWidth="400.0" promptText="Add a User here ..." />
          <Button fx:id="userButton" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
        </children>
        <padding>
          <Insets left="20.0" right="500.0" top="5.0" />
        </padding>
      </TilePane>
      <StackPane fx:id="tablePane" maxHeight="1.7976931348623157E308" minHeight="-Infinity">
        <children>
          <TableView fx:id="itemsTable" editable="true">
            <columns>
              <TableColumn text="Id" fx:id="idColumn">
                <cellValueFactory>
            <PropertyValueFactory property="id" />
                </cellValueFactory>
              </TableColumn>
              <TableColumn text="Name" fx:id="nameColumn" />
          <cellValueFactory>
            <PropertyValueFactory property="name" />
                </cellValueFactory>
              <TableColumn text="Price" fx:id="priceColumn" />
              <cellValueFactory><PropertyValueFactory property="price" />
                  </cellValueFactory>
              <TableColumn text="Quantity" fx:id="quantityColumn" />
              <cellValueFactory><PropertyValueFactory property="quantity" />
                  </cellValueFactory>
            </columns>
          <!--  <items>
                <FXCollections fx:factory="itemList">
                    
                </FXCollections>
            </items> -->
          </TableView>
        </children>
        <padding>
          <Insets left="20.0" right="20.0" top="20.0" />
        </padding>
      </StackPane>
    </VBox>
  </children>
</Group>
The strange behavior is if i comment <cellValueFactory></cellValueFactory> of nameColumn, priceColumn, and quantityColumn the problem thosent exist.

That is comment version of FXML :
<Group fx:id="salesWindow" xmlns:fx="http://javafx.com/fxml" fx:controller="org.warehouse.fxml.windows.controllers.SalesWindow">
  <children>
    <VBox>
      <TilePane fx:id="tilePane" hgap="-32.0" maxHeight="-Infinity" prefColumns="2" tileAlignment="TOP_LEFT" vgap="10.0" VBox.vgrow="ALWAYS">
        <children>
          <TextField fx:id="partnerField" alignment="CENTER" minHeight="30.0" minWidth="400.0" promptText="Add your Partner here" />
          <Button fx:id="partnerButton" alignment="CENTER" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
          <TextField fx:id="storeField" minHeight="30.0" minWidth="400.0" promptText="Add a Store here ..." />
          <Button fx:id="storeButton" alignment="CENTER" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
          <TextField fx:id="userField" minHeight="30.0" minWidth="400.0" promptText="Add a User here ..." />
          <Button fx:id="userButton" mnemonicParsing="false" text="..." TilePane.alignment="CENTER_LEFT" />
        </children>
        <padding>
          <Insets left="20.0" right="500.0" top="5.0" />
        </padding>
      </TilePane>
      <StackPane fx:id="tablePane" maxHeight="1.7976931348623157E308" minHeight="-Infinity">
        <children>
          <TableView fx:id="itemsTable" editable="true">
            <columns>
              <TableColumn text="Id" fx:id="idColumn">
                <cellValueFactory>
            <PropertyValueFactory property="id" />
                </cellValueFactory>
              </TableColumn>
              <TableColumn text="Name" fx:id="nameColumn" />
          <!--<cellValueFactory>
            <PropertyValueFactory property="name" />
                </cellValueFactory>-->
              <TableColumn text="Price" fx:id="priceColumn" />
              <!--<cellValueFactory><PropertyValueFactory property="price" />
                  </cellValueFactory>-->
              <TableColumn text="Quantity" fx:id="quantityColumn" />
              <!--<cellValueFactory><PropertyValueFactory property="quantity" />
                  </cellValueFactory>-->
            </columns>
          <!--  <items>
                <FXCollections fx:factory="itemList">
                    
                </FXCollections>
            </items> -->
          </TableView>
        </children>
        <padding>
          <Insets left="20.0" right="20.0" top="20.0" />
        </padding>
      </StackPane>
    </VBox>
  </children>
</Group>
The result is here :



If someone have any sugestion ... please help.
  • 1. Re: Invalid property. I cant understend what is the reason for this Exception!
    James_D Guru
    Currently Being Moderated
    In the FXML, the tags for the name column, price column, and quantity column are not properly structured. You have empty tags for each:
    <TableColumn text="Name" fx:id="nameColumn" />
    with no explicit close tag, so the cellValueFactory tag is a child of the TableView tag, not of the TableColumn tag. You need
    <TableColumn text="Name" fx:id="nameColumn" >
    <cellValueFactory>...</cellValueFactory>
    </TableColumn>
    Incidentally, you also have threading issues. You use the itemsList as the list of items for your table, so you shouldn't modify it outside of the FX Application Thread: your retrieveDBItems(...) method does exactly this.
  • 2. Re: Invalid property. I cant understend what is the reason for this Exception!
    idle Newbie
    Currently Being Moderated
    Ooohoo dude thanks, i got into Copy/Paste hell. About threading issue, why this aprouch is not correct ?
  • 3. Re: Invalid property. I cant understend what is the reason for this Exception!
    James_D Guru
    Currently Being Moderated
    There are two rules (well, there are probably more, but there are two big rules) for multithreading in FX:

    1. Don't do anything time consuming on the FX Application thread.
    2. Don't modify the UI on a background thread (i.e. on any thread except the FX Application thread).

    Your database access is an example of something time consuming, so quite correctly, you're using a Task to do the database access on a background thread (satisfying rule 1). However, you've called
    itemsTable.setItems(itemList);
    which means the TableView is observing itemList for changes, and will update its display in response to those changes. So when you call
    itemList.add(...);
    inside your Task.call(...) method, you violate rule 2. (See http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html which discusses this to some extent. In particular "Great care must be taken to never update shared state from any thread other than the FX Application Thread.")

    To fix, change the type of your Task to ObservableList<ItemProperty<Items>>, create a new list at the beginning of your call(...) method, populate that list in the for loop, and return it at the end of the method.
    Then register a listener with the task using task.setOnSucceeded(...). The event handler is called on the application thread, so in there you can retrieve the list you populated with task.getValue() and use it to populate your table with itemsTable.getItems().setAll(...) or itemsTable.getItems().addAll(...) (which one depends on your application logic, though in the initialize stage they are probably equivalent).
  • 4. Re: Invalid property. I cant understend what is the reason for this Exception!
    idle Newbie
    Currently Being Moderated
    Thank you for the advice .
  • 5. Re: Invalid property. I cant understend what is the reason for this Exception!
    idle Newbie
    Currently Being Moderated
    Sorry for my late post but i was so busy.
    Whatever, is that you mean in previous post ?
    public class SalesWindow implements Initializable {
        
        @FXML
        private TableView<ItemProperty<Items>> itemsTable;
        @FXML
        private TableColumn<ItemProperty<Items>, String> idColumn;
        @FXML
        private TableColumn<ItemProperty<Items>, String> nameColumn;
        @FXML
        private TableColumn<ItemProperty<Items>, String> priceColumn;
        @FXML
        private TableColumn<ItemProperty<Items>, String> quantityColumn;
        
        private final ExecutorService executorService = Executors.newCachedThreadPool(); 
        
         public Task<ObservableList<ItemProperty<Items>>> retrieveDBItems(){
            return new Task<ObservableList<ItemProperty<Items>>>() {
    
                @Override
                protected ObservableList<ItemProperty<Items>> call() throws Exception {
                    final ObservableList<ItemProperty<Items>> items = FXCollections.observableArrayList();
                    final ItemsJpaController jpaController = new ItemsJpaController(DBconnect.getEntityManagerFactory());              
                    for(Items i : jpaController.findItemsEntities()){
                        items.add(new ItemProperty<>(String.valueOf(i.getItemsPK().getId())
                                , i.getName(), String.valueOf(i.getPrice()), String.valueOf(i.getQuantity()), i));
                    }
                    return items;
                }
    
            @Override
            protected void succeeded() {
              super.succeeded();
              itemsTable.getItems().addAll(this.getValue());
            }           
            };
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            executorService.submit(this.retrieveDBItems());
        }
        
    }
  • 6. Re: Invalid property. I cant understend what is the reason for this Exception!
    James_D Guru
    Currently Being Moderated
    Yes, that's it.

    I usually use event handlers for the state transition rather than overriding the succeeded() method, but that's really just a style choice.
    With an event handler it looks like this:
         public Task<ObservableList<ItemProperty<Items>>> retrieveDBItems(){
            final Task<ObservableList<ItemProperty<Items>>> task = new Task<ObservableList<ItemProperty<Items>>>() {
     
                @Override
                protected ObservableList<ItemProperty<Items>> call() throws Exception {
                    final ObservableList<ItemProperty<Items>> items = FXCollections.observableArrayList();
                    final ItemsJpaController jpaController = new ItemsJpaController(DBconnect.getEntityManagerFactory());              
                    for(Items i : jpaController.findItemsEntities()){
                        items.add(new ItemProperty(String.valueOf(i.getItemsPK().getId())
                                , i.getName(), String.valueOf(i.getPrice()), String.valueOf(i.getQuantity()), i));
                    }
                    return items;
                }
            };
     
            task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
              @Override
              public void handle(WorkerStateEvent event) {
                itemsTable.getItems().addAll(task.getValue());
              }
           });
           return task ;
        }
    Edited by: James_D on Jan 26, 2013 7:26 AM
  • 7. Re: Invalid property. I cant understend what is the reason for this Exception!
    idle Newbie
    Currently Being Moderated
    Tnahk you for answers .

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points