Offline/online synchronization with Bikini: All a model needs

mway_bikini_blog03

Bikini is not just a fancy name for an outfit where 90% of a woman’s body is exposed. Bikini in a mobile app developing context also tries to address the most common synchronization problems you have with a mobile app. In short, you get offline/online synchronization and live updates of your collection. For our new version of The-M-Project we decided to use backbone.js as the base and build extensions needed to develop mobile web applications.

These extensions can be splitted into two parts:

  1. The UI-Part, extending the Backbone.View to make it easy to create all the fancy views needed in a mobile App and to allow TwoWay data binding.
  2. The DATA-Part, extending Backbone.Model and Backbone.Collection to use data stores and entities

This blog article will cover the data part and how we want to address the common problems with client/server data synchronization, offline storage and live data updates with our special bikini store.

The Goal

To make our framework suitable for HTML5 Web Apps, we want to store data also locally in a local storage, webSQL database or any future technology. Also, it should be easy as possible to get data synchronized from the server into a local store, make it editable offline and also getting live data changes if the client is online.

These things are easily said and a lot of other frameworks out there are doing similar, but most of them don’t support offline storage. So if you close the app and open it again you need a server connection to read the data again. It was clear we want to support a simple node.js version of the server as well as a more sophisticated java implementation in our own application server, the mCAP Mobility Platform.

After trying a lot of other frameworks, we came to the conclusion that we need to write our own piece of code to get this feature working.

The Bikini way

Very fast it was clear, we would like to have a simple REST interface as a base, so that other clients can use it as well. Next to this, it is the most robust way to transfer data and web sockets for notifications. For the web socket part we chose the socket.io framework as transport layer, because it provides a lot of fallbacks like long polling for all that mobile browsers not having web sockets implemented yet.

On the java side we use the Atmosphere framework, wich also has a socket.io implementation. To keep all possible documents without a schema we are using a mongodb open source database server side and our M.WebSqlStore on the client site. All changes to the documents are also stored in a change log on the server as well as on the client to provide a clean way to request all merged changes from the server and send all offline changes from the client when it gets online the next time.

To keep the merge conflicts and the traffic as low as possible we want to send only the changed attributes of each document as patches (on this point there is still work to do).

mway_bikini_blog04

Our data extension to Backbone.js

If you are familiar to backbone.js, you know it is very simple to use models and collection to access REST Interfaces like this:

	var contacts = Backbone.Collection.design({ // short for extend + create
		url: 'http://nerds.mway.io:8200/bikini/contacts', // url to the entity on the rest server
	});

	contacts.fetch({
		success: function(resp) {
			console.log('fetched ' + resp.length + ' records.');
		}, 
		error: function() {
			console.log('error fetching contacts.');
		}
	});

But we want to fetch and save data not only from a REST server but also to different other locations (stores). In Backbone all the transfer to the backend is going through the Backbone.sync function, and the usual way to change this is to override model.sync and collection.sync, and this is also exactly what we do. When you are using The-M-Project you get an M.Model and M.Collection enhanced by lot of functions for storing and transforming data, see this little first documentation for more details.

In short, you can use a store in your collection, and this is all you need to know for the first bikini tries.

Using Bikini is quite easy

The sample first:

	var users = M.Collection.extend({
		model: M.Model.design({ idAttribute: '_id' }),
		url: 'http://nerds.mway.io:8200/bikini/users',
		store: M.BikiniStore().create()
	});

As you see the only difference to plain Backbone is using the M namespace and the new store property.

Using the M.BikiniStore does all the magic for you:

  • data will be fetched and saved from and to the local store first (WebSql by default)
  • local changes will be send to the server as soon as possible (when the client is / gets online)
  • remote changes will be published into your collection as soon as possible (on app start or live when you are online)

For sure every thing can also be turned off, and the local store can be replaced if needed.

	var users = M.Collection.extend({
		model: M.Model.design({ idAttribute: '_id' }),
		url: 'http://nerds.mway.io:8200/bikini/users',
		store: M.BikiniStore().create({
			useLocalStore:   false, // (true by default) store the data for offline use
		    useSocketNotify: false, // (true by default) register at the server for live updates
		    useOfflineChanges: true, // (true by default) allow changes to the offline data
		    localStore: M.LocalStorageStore // (M.WebSqlStore by default) where to save data and change log
		})
	});

Conclusion

The-M-Project is in Beta now as well as Bikini, there is for sure a lot of work to do, but for the first shot it is working good and we are very happy with it. Feel free to test it and give feedback. Here you can find our address book sample to play with.

One thought on “Offline/online synchronization with Bikini: All a model needs

  1. Pingback: So long 2013 – looking back at this year’s blog highlights | Thinking Mobile Blog

Leave a Reply

Your email address will not be published. Required fields are marked *