Usage
Sinobu provides a simple mechanism for persisting the state of objects
using the Storable
interface. This allows objects to save their properties
to JSON file and restore them later, making it easy to maintain application
state across restarts.
ðĶĪ Interface Based
Implement the Storable
interface on your class to enable persistence.
class Data implements Storable<Data> {
public int property;
}
âïļ Saving Data
The Storable#store()
method saves the current state of the object's properties
to file. (check property)
void save() {
Data data = new Data();
data.property = 10;
data.store(); // save data to file
}
âïļ Restoring Data
The Storable#restore()
method restores the object's properties from file (check
property). If the file doesn't exist or
an error occurs during reading/parsing, the operation typically fails silently, leaving
the object in its current state (often default values).
void restore() {
Data other = new Data();
other.restore(); // load data from file
assert other.property == 10;
}
Transient
Normally all properties are eligible for preservation, but there are several ways to make explicit which properties you do not want to preserve.
If the property is defined by field, add the transient modifier to the field declaration.
class TransientField implements Storable<TransientField> {
public transient int unstorableProperty;
}
If the property is defined by method, add java.beans.Transient
annotation. (You
only need to add it to either the setter or the getter)
class TransientMethod implements Storable<TransientMethod> {
private int value;
@java.beans.Transient
public int getUnstorableProperty() {
return value;
}
public void setUnstorableProperty(int value) {
this.value = value;
}
}
Automatic Saving
Instead of manually calling Storable#store()
every time a change occurs,
you can be configured to save their state automatically when their properties change.
This is achieved using the Storable#auto()
method.
Since monitoring the values of arbitrary properties would be prohibitively expensive,
value detection is only possible for properties defined by Variable
.
Calling Storable#auto()
instance monitors its (and nested) properties.
When a change is detected, it schedules a save operation. By default, this operation is
debounced (typically waiting 1 second after the last change) to avoid excessive writes
during rapid changes.
void autoSave() {
class Data implements Storable<Data> {
public final Variable<String> name = Variable.empty();
}
Data data = new Data();
data.auto(); // enable auto-save
data.name.set("Misa"); // save after 1 sec
}
Calling Disposable#dispose()
on the returned object will stop the automatic
saving process for that instance.
void stopAutoSave() {
class Data implements Storable<Data> {
public final Variable<String> name = Variable.empty();
}
Data data = new Data();
Disposable stopper = data.auto();
stopper.dispose(); // stop auto-save
}
Storage Location
By default, persistence file is stored in a directory named .preferences
within
the application's working directory. The filename is derived from the fully qualified
class name of the storable object, ending with .json
.
(e.g., .preferences/com.example.MyAppSettings.json
).
This location can be customized in two main ways:
Location Method
You can override the Storable#locate()
method within your implementing class
to return a custom Path
for the persistence file.
class Custom implements Storable<Custom> {
public Path locate() {
return Path.of("setting.txt");
}
}
Environment Variable
You can set a global preference directory by defining the environment variable
PreferenceDirectory
using I#env(String, Object)
. If this variable is set,
the default implementation will use this directory instead of .preferences
.
void define() {
I.env("PreferenceDirectory", "/user/home/setting");
}