JavaFX with JPA

To Put or not to put JavaFX Properties into Entities?

Just some ideas that I found and will test some day

Approach 1

JavaFX Property into Entity with “super lazy” behavior

// FROM: https://stackoverflow.com/questions/32973827/javafx-property-based-entity-vs-property-based-wrapper

@Entity
@Access(AccessType.PROPERTY)
public class Person {
   private IntegerProperty age ;
   private int _age ;
   private StringProperty name ;
   private String _name ;

   private int id ;

   @Id
   public int getId() {
      return id ;
   }
   public void setId(int id) {
      this.id = id ;
   }

   public IntegerProperty ageProperty() {
        if (age == null) {
            age = new SimpleIntegerProperty(_age);
        }
        return age ;
    }

    public int getAge() {
        if (age == null) {
            return _age ;
        } else {
            return age.get();
        }
    }

    public void setAge(int age) {
        if (this.age == null) {
            _age = age ;
        } else {
            this.age.set(age);
        }
    }

    public StringProperty nameProperty() {
        if (name == null) {
            name = new SimpleStringProperty(_name);
        } 
        return name ;
    }

    public String getName() {
        if (name == null) {
            return _name ;
        } else {
            return name.get();
        }
    }

    public void setName(String name) {
        if (this.name == null) {
            _name = name ;
        } else {
            this.name.set(name);
        }
    }
}

Approach 2

JavaFX Property into Entity with Property Change Listener

// FROM: https://stackoverflow.com/questions/32973827/javafx-property-based-entity-vs-property-based-wrapper

@Entity
public class Person {
    @Id
    private int id ;

    private int age ;
    private String name ;

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public int getAge() {
        return age ;
    }

    public void setAge(int age) {
        int oldAge = age ;
        this.age = age ;
        pcs.firePropertyChange("age", oldAge, age);
    }

    public String getName() {
        return name ;
    }

    public void setName(String name) {
        String oldName = name ;
        this.name = name ;
        pcs.firePropertyChange("name", oldName, name);
    }

    // ...
}

Approach 3

JavaFX Property into Entity with Simple*Property

// FROM: https://stackoverflow.com/questions/23522130/javabean-wrapping-with-javafx-properties

@Entity
@Access(AccessType.PROPERTY)
public class Person {
   private final StringProperty firstName = new SimpleStringProperty(this, "firstName");

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

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

   public StringProperty firstNameProperty() {
      return firstName ;
   }
    // ... other properties, etc
}

Approach #4

JavaFX Property outside Entity

public class PersonProperties {
   private final Person person;

   public PersonProperties(Person person) {
      this.person = person;
   }

   private final StringProperty name = new SimpleStringProperty() {
      @Override
      public void set(String string) {
         super.set(string);
         person.setName(string);
      }
   }

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

   public final void setName(String value) {
      name.set(value);
   }
}

Approach 5

JavaFX Property unidirectional outside Entity. Property generated by Property Adapter factory and Simple entity (without property change listeners)

PS: property unidirectional (change the value in the table, the entity will be updated BUT change value in entity will not update the value displayed)

// FROM: https://stackoverflow.com/questions/31941805/put-together-javafx-properties-and-jpa-entities-no-mixed-mode
@Entity
public class Person {

    private String firstName ;
    private String lastName ;

    @Id
    private Integer id ;

    public String getFirstName() {
        return firstName ;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName ;
    }

    public String getLastName() {
        return lastName ;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName ;
    }
}
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(cellData -> {
    try {
        return JavaBeanStringPropertyBuilder.create()
            .bean(cellData.getValue())
            .name("firstName")
            .build();
    } catch (NoSuchMethodException exc) {
        throw new RuntimeException(exc);
    }
});

Approach 6

JavaFX Property bidirectional binding outside Entity

Property generated by Property Adapter factory and Entity with property change listeners

// FROM: https://stackoverflow.com/questions/31941805/put-together-javafx-properties-and-jpa-entities-no-mixed-mode

@Entity
public class Person {
    private String firstName ;
    private String lastName ;

    private PropertyChangeSupport pcs ;

    public Person() {
        pcs = = new PropertyChangeSupport(this);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(listener);
    }

    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        String oldName = this.firstName ;
        this.firstName = firstName;
        pcs.firePropertyChange("firstName", oldName, this.firstName);
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        String oldName = this.lastName ;
        this.lastName = lastName;
        pcs.firePropertyChange("lastName", oldName, this.lastName);
    
TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
firstNameCol.setCellValueFactory(cellData -> {
    try {
        return JavaBeanStringPropertyBuilder.create()
            .bean(cellData.getValue())
            .name("firstName")
            .build();
    } catch (NoSuchMethodException exc) {
        throw new RuntimeException(exc);
    }
});

Approach 7

Adapter pattern

// FROM  https://stackoverflow.com/questions/31941805/put-together-javafx-properties-and-jpa-entities-no-mixed-mode

// normal entity with getters and setters
@Entity
public class EntityClass implements Serializable {
   @Id
   private Integer id;

   public Integer getId() {
      return id;
   }

   public void setId(Integer id) {
      this.id = id;
   }

   public String getYear() {
      return year;
   }

   public void setYear(String year) {
      this.year = year;
   }
}
public interface IFXEntity {
   void setYear(String year);
   String getYear();
}
public class FXEntityClass implements IFXEntity {
   private final StringProperty yearProperty = new SimpleStringProperty();

   private StringProperty getYearProperty() {
      return yearProperty;
   }

   public setYear(String year) {
      this.yearProperty.set(year);
   }

   public String getYear() {
      this.yearProperty.get();
   }
}
public class EntityClassToFXEntityClassAdaptor implements IFXEntityClass{
   private EntityClass entity;
   private final StringProperty yearProperty=new SimpleStringProperty();

   public EntityClassToFXEntityClassAdaptor(EntityClass e){
      this.entity = e;
      this.yearProperty.set(e.getYear());
   }
   public StringProperty getYearProperty(){
      return this.yearProperty;
   }
   public void setYear(String year) {
      this.year.set(year);
   }
   public String getYear() {
      return this.year.get();
   }
}
EntityClass ec=something; //get an instance of JPAEntity

EntityClassToFXEntityClassAdaptor adaptor=new EntityClassToFXEntityClassAdaptor(ec);
adaptor.getYearProperty();

Approach 8

JavaFX property outside Entity. Using PropertyValueFactory

import javafx.fxml.Initializable;
import javafx.scene.control.cell.PropertyValueFactory

public class PersonDataController implements Initializable;

@FXML private TabelColumn<Person, String> colFirstName;
@FXML private TabelColumn<Person, String> colLastName;

@Override
public void initialize(URL localtion, ResourceBundle resources) {
   colFirstName.setCellValueFactory(new PropertyValueFactory<Person,String>("FirstName"));
   colLastName.setCellValueFactory(new PropertyValueFactory<Person,String>("LastName"));
}

???

// FROM: https://stackoverflow.com/questions/23522130/javabean-wrapping-with-javafx-properties

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Bean {
   private String name ;
   private final PropertyChangeSupport propertySupport ;

   public Bean(String name) {
      this.name = name ;
      this.propertySupport = new PropertyChangeSupport(this);
   }

   public Bean() {
      this("");
   }

   public String getName() {
      return name ;
   }

   public String setName(String name) {
      String oldName = this.name ;
      this.name = name ;
      propertySupport.firePropertyChange("name", oldName, name);
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      propertySupport.addPropertyChangeListener(listener);
   }
}

????
StringProperty nameProperty = new JavaBeanStringPropertyBuilder().bean(??).name("name").build();

Bean bean = new Bean();
StringProperty nameProperty() = new JavaBeanStringPropertyBuilder()
        .bean(bean)
        .name("name")
        .build();
nameProperty().addListener((obs, oldName, newName) -> System.out.println("name changed from "+oldName+" to "+newName));
bean.setName("James");
System.out.println(nameProperty().get());