Yesterday we announced the availability of Gluon Cloud, and we briefly touched on its two main functions: data synchronization between different devices, and data connectivity with back end and cloud systems. Today, we’ll focus a bit more on the data synchronization aspects of Gluon Cloud.
Almost every useful client application is useful because it shares data with back end systems or because it communicates to other installations of the client application. In a restaurant review app, reviews should be shared with other users of the app. In enterprise applications using forms, data must be stored on a server. In social applications, actions performed by a user should be visible to other users. It is this ability to share information with other interested systems (and users) that provides the value in the application itself.
In short – implementing this kind of functionality requires code to be written that synchronizes the data on the client application with a remote persistence system. Once the data is synchronized up to the remote persistence system, it can then be retrieved by other devices, or pushed to them from the remote persistence system. There are a number of options that come with this synchronization:
- In case local data changes, do we want the remote copy to be changed immediately as well? We call this option write-through support.
- In case the remote copy of the data changes, do we want all local copies to be changed immediately as well? This is what we refer to as read-through support.
Clearly, some applications need read-through and write-through support (e.g. an online chat application), where others don’t need read-through and write-through support, and are better off by performing a manual synchronization operation when necessary. Gluon Cloud supports all these scenarios and integrates them very well into the existing JavaFX pattern of ObservableObject
and ObservableList
. We will discuss the ObservableObject
first.
ObservableObject
In a typical JavaFX Application, the content of a UI control is bound to data that can be changed, i.e. a JavaFX Observable
or a JavaFX ObservableList
:
Label authorLabel = new Label(); authorLabel.textProperty().bind(comment.authorProperty());
where authorProperty()
is a StringProperty
(and hence an Observable
) declared on the Comment
class. This way, local data binding is achieved. We can use remote data binding by having the comment initialized as follows:
CharmObservableObjectcomment = storageService.retrieveObject("personalComment", Comment.class, StorageWhere.GLUONCLOUD);
The comment object is now a CharmObservableObject
which implements ObservableObject
. Whenever a CharmObservableObject
changes, its listeners are fired and interested components are notified. However, when the object changes locally or in Gluon Cloud, nothing will happen. To persist the local changes in Gluon Cloud, we call the manual synchronization method:
comment.sync();
This will push the data to Gluon Cloud and make sure it is persisted there. The sync()
method can be useful when you want to let the application decide at what time changes should be written. If you don’t need this level of control, you specify synchronization flags to tell your application that the changes can be written automatically without the need to call the sync()
method:
CharmObservableObjectcomment = storageService.retrieveObject("personalComment", Comment.class, StorageWhere.GLUONCLOUD, SyncFlag.OBJECT_WRITE_THROUGH);
Now, whenever the value of the author property changes, these changes will be automatically pushed to Gluon Cloud as well.
The final step we can add is to activate read-through support so that changes that happen on the comment object in Gluon Cloud will automatically be synchronized with our local copy. Providing an extra synchronization flag does the trick:
CharmObservableObjectcomment = storageService.retrieveObject("personalComment", Comment.class, StorageWhere.GLUONCLOUD, SyncFlag.OBJECT_WRITE_THROUGH, SyncFlag.OBJECT_READ_THROUGH);
Combining OBJECT_WRITE_THROUGH
and OBJECT_READ_THROUGH
allows real-time collaboration between different instances of the application. If one client adds a comment, it will immediately be sent to Gluon Cloud in case the SyncFlag.OBJECT_WRITE_THROUGH
is used. If the SyncFlag.OBJECT_READ_THROUGH
is set as well, the comment variable in all other connected clients will be updated as well.
ObservableList
ObservableList
is a very familiar JavaFX concept as well. It is used when you want to take action when elements in the list are added or removed, which is for example done in a ListView
:
ObservableListcomments = FXCollections.observableArrayList(); ListView listView = new ListView<>(); listView.setItems(comments);
Again, this is how you would create a binding between the content of a UI control and local data. When elements are added or removed from the comments list, the changes will be visible on the UI control as well. We can upgrade the local list to a remote list on Gluon Cloud by changing the ObservableList
to a CharmObservableList
:
CharmObservableListcomments = storageService.retrieveList("publicComments", Comment.class, StorageWhere.GLUONCLOUD);
In contrast with CharmObservableObject
, read-through and write-through synchronization are enabled by default for lists. This means that adding or removing elements will also add and remove them from the persisted list on Gluon Cloud. If you don’t want to enable synchronization, you can pass in an empty array of synchronization flags:
CharmObservableListcomments = storageService.retrieveList("publicComments", Comment.class, StorageWhere.GLUONCLOUD, new SyncFlag[] {});
Synchronization can then be done only when you call the sync()
method, exactly like you would for a CharmObservableObject
:
comments.sync();
With a CharmObservableList, there are two levels of synchronization. On one hand we have the elements inside the list itself which can be added or removed. On the other hand we have the objects that are contained inside the list of which their fields can change. The first level is controlled by SyncFlag.LIST_WRITE_THROUGH
and SyncFlag.LIST_READ_THROUGH
, the second level with SyncFlag.OBJECT_WRITE_THROUGH
and SyncFlag.OBJECT_READ_THROUGH
.
Summary
Data synchronization is an important aspect in modern client development. There are different ways to synchronize, and the best way depends on the nature of your application and its environment. Gluon Cloud supports different synchronization options, and allows the developer to decide which option to use for specific data without having to write lots of boilerplate code.
Because the API is always in development, we recommend that developers who want to use this functionality refer to the Gluon Mobile developer documentation for the very latest instructions on storage and synchronization.