How do we properly track changes to an object's properties in Java (specifically JavaFX)?
My application allows users to modify the properties of the underlying data model objects. When the user clicks on a "Save" button, I want to save the new state of the object to a database. However, if the user clicks on "Cancel," I need to revert back to the object's original state.
Consider the following example objects (getters omitted for clarity):
class Person {
private final StringProperty name = new SimpleStringProperty();
private final StringProperty email = new SimpleStringProperty();
private final SimpleListProperty<PhoneNumber> phoneNumbers = new SimpleListProperty<>();
public Person(String name, String email, ObservableList<PhoneNumber> phoneNumbers) {
this.name.set(name);
this.email.set(email);
this.phoneNumbers.set(phoneNumbers);
}
}
class PhoneNumber {
private final IntegerProperty areaCode = new SimpleIntegerProperty();
private final IntegerProperty prefix = new SimpleIntegerProperty();
private final IntegerProperty lineNumber = new SimpleIntegerProperty();
public PhoneNumber(int areaCode, int prefix, int lineNumber) {
this.areaCode.set(areaCode);
this.prefix.set(prefix);
this.lineNumber.set(lineNumber);
}
}
Ideally, I want the GUI to load the original Person
object, and make a copy of it to bind to the UI controls (even if I need to write this method myself):
Person editedPerson = copyOf(originalPerson);
Then, if the user clicks "Cancel," do nothing. Upon clicking "Save," however, set originalPerson
to be equal to editedPerson
.
I have looked into cloning objects, but the general consensus seems to recommend against that as it does not ensure the original object is not changed. Also, unless doing a deep copy, any objects references within Person
, for example, would not be properly copied.
The other option I've seen is to use a copy constructor but my real-world application uses much more complex objects than the sample above. There are several levels of objects nested within each object and manually copying the entire hierarchy seems like overkill.
So what is the main question? Is there already an API available (or 3rd party library) that handles this functionality? It seems to be a pretty standard expectation for a user to be able to revert their changes.