Tuesday, October 2nd, 2007
Persistent Objects with Persevere the client and Jsponic the server
Kris Zyp has made a charge in the persistent JavaScript space by releasing both a client and a server to handle JSON persistence.
Persevere s an open source persistent object mapping framework for JavaScript in the browser. Persevere allows programmers to access, traverse, and manipulate persisted data easily with standard JavaScript syntax and intuitive Persistent JavaScript (PJS). Persevere implements the PJS API and maps JavaScript objects to persistent storage objects remotely through JSON based RESTful web services following the JSPON (JavaScript Persistent Object Notation) data interchange specification. Persevere accesses persisted object graphs provided through JSPON data sources which can represent various underlying sources such as database tables and can even span domains. Persevere can provide orthogonal persistence and lazy loading support with standard JavaScript property access and modification through JavaScript optional pre-processing, such that persisted data can be modified with plain JavaScript, for example:
-
-
var result = pjs.load("data or query id"); // load a object mapped to
-
persistent data
-
var object = result[1]; // access items from a result
-
var value = object.prop; // lazy loading is performed when necessary
-
object.prop = "new value"; // change a property and it is automatically sent
-
to the server to be persisted
-
result.push({name:"new object/row"}) // adding and removing rows/objects
-
from persisted data can be done with normal JS array methods
-
Array.remove(result,object); // or splice
-
Persevere can also be used without preprocessing, or it can provide these
capabilities natively with JavaScript 1.7. Persevere allows supports
application code to be persisted and exist within these object graphs, to
facilitate a unique "live programming" approach to object oriented design
and organization.
Jsponic provides a server implementation of the JSPON protocol, and therefore is ideal as a backend for Persevere (or any other JSPON client). Jsponic is a Java-based server that implements the JSPON protocol for exposing persistent data storage as RESTful JSON web services, and with full capabilities for modification of persisted data, execution of remote/distributed JavaScript methods, and data centric object level security. Jsponic includes an internal dynamic object database, and supports standard SQL tables, XML files, and web service, and exposes these data sources through JSON. Jsponic also implements the PJS specification, and provides persistent object mapping in a server local JavaScript environment (Rhino) which facilitates distributed remote calls between the client and server with both environments referencing and sharing access to the same persisted data.
Persevere and Jsponic can be used independently of each other, as communication is based completely on JSON (JSPON and JSON-RPC), and it is easy to implement these publicly available specifications to write your own client to connect to Jsponic or build your web service as a backend to Persevere. Persevere and Jsponic both come with the JSPON Object Browser to facilitate testing, accessing, and manipulating JSPON data to simplify building your own client or server.












The links are broken. Also, you forgot to put in a link to the original story at Json.com
While i get the whole persistency thing, i think this is kinda over-the-top (as with most Java-based stuff)
For instance, i quote (from the specs):
Now WHY would you want to communicate this stuff with every change? You’re going to do a JSON request via a JSON dialect to update a JSON array ? This is (IMO) typically the Java kind-of-thinking: The server *must* know about everything that’s going on on the client and the server must do the processing.
If I would build a persistency layer, i’d transmit the whole serialized objects at the beginning of a user session to load something and at the end of the session (onUnload) to store the state.
We have done this way easier over at http://www.widgetplus.com ..
SchizoDuckie: Persevere does indeed wrap up all the changes that occur in a given event into a single request (it doesn’t try to send each one individually). This also provides implicit transaction wrapping. However, it doesn’t usually wait for the end of the session. While that is certainly possible to do with Persevere, that does not seem to be advantageous, generally you want information to get back to the server as soon as possible so that other clients can use it.
Mikael: I don’t see any info on your site about persistence, it looks like it is about widgets. And actually the persevere project originally sprung from a widget based framework Authenteo, but I realized that developers probably want a solution that doesn’t require there whole UI tightly coupled to their persistence layer.
Mikael, please stop spamming Ajaxian. I’ve seen you link to your homepage at least 3 times in the past month or so (http://ajaxian.com/archives/google-launches-javascript-api-that-allows-you-to-write-back).
But you never link to anything useful to the discussion.
If widgetplus does have something to offer to the topic at hand, please link to a page that explains more.
Kris, I’m using RoR, but I’m often making RESTful JSON services. Something like – get: /tasks/1 returns
{ id: 2, name: ‘mow lawn’ }
On a high level,
What would I have to do to change Rails default services to implement JSPON?
Does JSPON rest services use the same type of URL method maping (i.e. get, post, put, delete, with urls like /tasks/1) as typical REST services?
Assuming the conversion would be trivial, how would I open the resource?
Would their be a different pjs for each model? Something like:
taskpjs = new PJS(’/tasks’)
taskpjs.load(1)
projectpjs = new PJS(’/project)
projectpjs.load(18);
If a project had many tasks, I’d also like to do something like
projectpjs.tasks
and get a list of tasks
Is this possible?
Justin,
PJS is not constructor, pjs is just a namespace for the API, but you have the right idea. So you could do:
tasks = pjs.load(’/tasks/’); // causes a get request for the url ‘/tasks’ and assumes that it returns a JSON array of tasks
tasks[1] == pjs.load(’/tasks/1′) // this should be true
And yes, if you have a relationships setup correctly, you could do
myproject = pjs.load(’/projects/18′)
mytask = myproject.tasks[2];
As far as the REST operations, Persevere currently does not use the PUT and DELETE verbs. Persevere uses a more idioms more similiar to JavaScript where you don’t delete objects, you delete references to objects, so DELETE is not really an appropriate verb. I can easily use the PUT verb, but to actually follow the HTTP spec for PUTs is just too constraining for dynamic data and scalability. In particular, Persevere wraps multiple operations into single requests. This improves performance and it provides a natural indication of transactions. I could use the PUT method to indicate that data is being put, but I have wanted to be more precise in sticking to the HTTP/REST specifications so I have not done that. I could certainly change that.
I would certainly be interested in seeing what would need to be done to implement JSPON compliance with RoR. Maybe I need to learn RoR…
“If widgetplus does have something to offer to the topic at hand, please link to a page that explains more”
Ok, this page in particular then, http://www.widgetplus.com/testbed2.htm
SchizoDuckie:
You are right, it was overly complicated, the client-server REST communication should be as simple and
readable as possible. I have revised Persevere to use semantic REST method communication that is simple
enough you can intuitively persist data to the Persevere server with simple XHR-HTTP requests using a
bare HTTP client (like RESTTest).