This post is written for Persevere 1.0 and Dojo 1.3. If you want to get started with Persevere 2.0 (recommended), take a look at this post. Dojo 1.6 and newer has a new data API as well.

The Persevere server is an open source JSON application and storage server. Persevere pairs well with Dojo; the Dojo Data paradigm has a strong correlation to Persevere’s data storage structure. Virtually everything you can create or action you can perform with Dojo Data can be persisted in Persevere’s data storage including subobjects, arrays, circular references, and functions. Combining Persevere with Dojo allows you to rapidly develop simple database applications with create, read, update, and delete (CRUD) capabilities with minimal effort.

Starting Persevere

To get Persevere running, first download the latest version of Persevere. Next, unzip the Persevere zip file into the directory you want to use for Persevere. Finally, go to the directory where you unzipped Persevere and run:

java -jar start.jar

Persevere should start up as long as Java is installed on your system. You can now access Persevere in your web browser by visiting http://localhost:8080/.

Creating a Persevere Class

The basic container for storage in Persevere is a class; analogous to a table in relational databases. A Persevere class holds object instances, and class style structures can be defined for the object instances including methods and type definitions for the object properties. To create a Persevere class, first open the object browser at http://localhost:8080/browser.html?id=root. The object browser allows you to browse and navigate the objects in Persevere. To create a class, click the button (make sure no object is selected). A dialog will ask you for the name of your class and what class to extend. We will call the class “Product” and we will accept the default base class of “Object”. You now have data storage structure which can hold Product object instances.

Connecting with Dojo

Persevere is compliant with the HTTP/REST protocol, so the JsonRestStore is very effective with Persevere. However, dojox.data.PersevereStore is an extension of JsonRestStore specifically designed to simplify connecting to Persevere and take advantage of extra features of Persevere. This architecture is designed for a data store instance per server table. With the PersevereStore we can easily get a set of data stores corresponding to the server tables/classes:

dojo.require("dojox.data.PersevereStore");
var deferred = dojox.data.PersevereStore.getStores();

This deferred object will provide an object map of the stores when finished. We can get the data store for our Product table:

deferred.addCallback(function(stores){
	productStore = stores.Product;
});

The data store can be used with various widgets that support data stores. For example to use this table with the Dojo Grid:

grid.setStore(productStore)

or you can set the productStore as the store in the constructor. For example:

grid = new dojox.grid.Grid({
	store: productStore,
	query: "",
}, dojo.byId("gridId"));

With the ability to define any type of object structure, a Persevere data store can be used with virtually any widget. With the referencing capabilities it can be used hierarchically, so it is also well suited for use with the Tree widget.

Create, Read, Update, and Delete

Via Dojo, interacting with Persevere can be done directly with the Dojo Data API. To create our first object instance in the Product table:

paintballGun = productStore.newItem({name:"Paintball Gun",price:129.99});
productStore.save();

We can easily read properties using directy property access or the Dojo Data API:

paintballGun.price -> 129.99
productStore.getValue(paintballGun,"price") -> 129.99

We can update properties:

productStore.setValue(paintballGun,"price",119.99);
productStore.save();

Note that we do not need to define any type of schema, columns, or structure for a table ahead of time, we can simply dynamically create properties on objects that we create.

And delete the objects as well:

productStore.deleteItem(paintballGun);

One of the powerful aspects of Persevere is that you can dynamically persist a large variety of data structures. For example, we could save a sub object with manufacturer information:

productStore.setValue(paintballGun,"manufacturer",{
	name:"HotShots",
	rating:4,
	started: new Date(Date.parse("Jul 09 2002")),
	topProduct:paintballGun
});

In this example, we are saving an object as a value, and even including Dates, and a circular reference (back to the product object). Virtually anything you can create with JavaScript can be persisted to Persevere.

Querying

An essential aspect of database interaction is querying. Here we can use the standard query-object convention used by Dojo Data to search for objects. A query object is an object with name-values corresponding to the search filters to apply (and wildcards are supported). For example to find all the objects with a name that starts with “Paintball”:

productStore.fetch({
	query: {name: "Paintball*"},
	onComplete: function(results){
		results[0] -> paintballGun
	}
});

We can also utilize sorting and paging as well. To sort by price (lowest to highest) and return items 20-29:

productStore.fetch({
	query: {name: "*"},
	sort: [{attribute:"price",descending:false}],
	start: 20,
	count: 10,
	onComplete: function(results){
		...
	}
});

Persevere also supports JSONPath/JSONQuery queries, which have a much greater level of expressibility and can be used for more sophisticated queries. For example to search for all the items with a price less than $100 or a rating greater than 3:

productStore.fetch({
	query: "[?price<100 | manufacturer.rating > 3]",
	onComplete: function(results){
		...
	}
});

Live Data with Comet

Dojo and Persevere support HTTP Channels which allows for addition of live data updates through Comet notifications. Adding Comet capability is simple, just add the HttpChannels module after the PersevereStore has been loaded:

dojo.require("dojox.data.PersevereStore");
dojo.require("dojox.cometd.HttpChannels");

This is all that is necessary. Dojo will automatically subscribe to all data that is accessed, notifications will be delivered to the client, and the notifications will result in cached data updates and Dojo Data API notifications (which will update the user interface on notification aware widgets like the Grid). No additional coding is necessary to utilize live data updates.

Setting up Security

Out of the box, security is disabled in Persevere to make it easier to begin development. However, security is a key feature of Persevere, allowing Persevere to be safely used directly on the web, accessible from your JavaScript environment. Prior to deployment you should of course enable security, and it is also enabled once the first user account is created. To create a user account, go to the object browser (http://localhost:8080/browser.html?id=root), click on the sign in button , and choose to create a new user. This first user is given the administrative privileges for the system. All data is accessible to this user, but is read only by default for all other users and public access. Additional users may be created by the same process (or programmatically), but subsequent users must be granted access to data.

To enable higher level access for the public or other created users, you can select an object or table and click on the grant access button in the object browser. You can then enter “public” for public access, or a user name to enable write access to the data.

Conclusion

You can see these simple data interaction techniques in sample code in the customers example included in the Persevere download (which can be viewed locally at http://localhost:8080/examples/customer.html) There are numerous other important capabilities of Persevere including server side JavaScript execution through JSON-RPC, schema definition, prototype objects, cross-site referencing, accessing existing SQL databases, and more that are described in the Persevere documentation and we will explore in future tutorials. You should now have enough information to get a quick start to building database applications with Persevere using the oft-used create, read, update, delete, and querying operations, and easily plugging into Dojo widgets, with support for live data updates. You can start building applications almost instantly; no need to create schemas or table definitions ahead of time, simply start creating and building dynamic persistent objects in your data stores, and connect them to widgets for display. You can build your entire application, client and server, in JavaScript.