Backbone.Rpc
Plugin for using the backbone js library with json-rpc instead of the native REST implementation
Build Status, Project Page, Annotated Source & Tests
Project Page
Docs
Tests
NPM registry
Introduction
In nearly every javascript developers life, there is a point when you need to work with rusty old Java devs. This happend to me when I created this plugin. Instead of using a nice RESTful interface, the backend guys came around with a json-rpc 2.0 implementation. It was clearly unusable with the default backbone request handling. So this little piece of software was the outcome of my will to use Backbone.
Installation
The plugin itself implements the Universal Module Definition (UMD). You can use it with a CommonJS like loader, or with an AMD loader or via vanilla javascript.
The plugin itself has three dependencies, underscore.js, jQuery and backbone.js
You can directly download the Development Version or the Production Version from the root folder
AMD
// AMD;
NPM
$ npm install Backbone.Rpc
CommonJS
// CommonJSvar Backbone = ;
Vanilla JS
<!-- Vanilla javascript -->
Usage
Basic usage
var TextModel = BackboneModel; // server will respond on calling the 'getRandomTextSnippet' method// with the following data:// {id: 12, headline: 'A remote headline', text: 'Loaded remotly'} var textModel = ;textmodel;
So, what happend here?!
We added a new Backbone.Rpc instance as an indicator, that this model will use the Backbone.Rpc.Sync function to communicate with the Server.
rpc:
Then, we told the Rpc plugin that we wan´t to map the Backbones fetch method to the remote method 'getRandomTextSnippet':
methods: read: 'getRandomTextSnippet'
This results in the following POST Request:
"jsonrpc":"2.0""method":"getRandomTextSnippet""id":"1331724849238""params"::
According to the JSON RPC Version 2 Specs, the Server will respond with something like this:
"id":"1331724849238""result":"id": "12" "headline": "A remote headline" "text": "Loaded remotly""jsonrpc":"2.0"
Backbone.Rpc will now take this Response and convert it to smth. Backbones "normal" response parser and model attribute mapping engine can understand.
Mapping more then one method
If you have more then one method to map (e.g. complete CRUD plus some other stuff) you can define them as follows:
var DeviceModel = BackboneModel;
Here we have five methods. The first four (read, create, remove, update) will be mapped to the corresponding Backbone methods.
Example:
deviceModel; // Calls 'read'deviceModel; // Calls 'create'deviceModel; // Calls 'update'deviceModel; // Calls 'remove'
But what will happen to the 'addDeviceToRoom' method? You can call it directly!
deviceModel; // Calls 'addDeviceToRoom' // This methods acts like all the other methods, so you can use options:deviceModel; // And you can bind eventsdeviceModel;
Adding params to the methods
You might wonder what that snd. array entry 'id' in our 'read' method is?!
read: 'getFilteredDevicesById' 'id'
It´s a placeholder for a param property. If we take a closer look at the Request from the 'Basic Usage' example, we see an empty params array.
"jsonrpc":"2.0""method":"getRandomTextSnippet""id":"1331724849238""params"::
If we now do the following and take a look at the request, our current example creates, we see what this will change:
deviceModel;deviceModel; // Calls 'read' // Request created by the 'read' call"jsonrpc":"2.0""method":"getFilteredDevicesById""id":"1331724849298""params":"14":
Hopefully you noticed that the contents of the 'id' attribute are applied as part of the params array in the response.
As seen in the update call, you can add as many as params as you like:
update: 'setDeviceName' 'id' 'name'
Using named parameters
The JSON-RPC 2.0 spec includes the support for passing parameters by-name. You can enabled this functionality by setting 'useNamedParameters' to true in your Backbone.Rpc options.
var DeviceModel = BackboneModel;...deviceModel;deviceModel; // Calls 'read' // Params is an object with named parameters"jsonrpc":"2.0""method":"getFilteredDevicesById""id":"1331724849298""params":"id":"14":
Fire multiple RPC calls with one method call
Sometimes we need to do more then one remote method call when we operate on an entity. Using our device example, we can say that every time a device will be created we need to reset the server side device cache.
Sure we could accomplish that by adding an 'invalidateCache' method to our model and calling it manually, every time a device will be updated. But that´s error prone. Luckily, we have a simple pattern to accomplish this.
var DeviceModel = BackboneModel; var deviceModel = ;deviceModel;
This results in two simultanious POST requests against the rpc handler.
// Creates the device"jsonrpc":"2.0""method":"addDevice""id":"1331724850010""params":"My new device": // Invalidates the cache"jsonrpc":"2.0""method":"invalidateCache""id":"1331724850020""params"::
Dynamicly created request methods
Lets stick with the multiple RPC call example a bit. Maybe you wan´t to only invalidate the Server cache under specific circumstances. To keep it´simple, only when the 'invalidate' attribute in the model is true. Mhhh... seems tricky?!
Functions to the rescue:
var DeviceModel = BackboneModel; // does not invalidate cachevar deviceModelOne = ;deviceModelOne; // invalidatesvar deviceModelTwo = ;deviceModelTwo; // again does not invalidate the cachevar deviceModelThree = ;deviceModelThree;
You get the idea...
Parsers
After all this fetching and calling methods, you might wonder what happens with the return value of remotly invoked functions that are not mapped to the 'read' method?! Short answer: Nothing.
Lets change that.
var DeviceModel = BackboneModel; var deviceModelThree = ;deviceModel;deviceModel;
Collections
You can add the Rpc functionality to Collections. Be aware that only fetching / reading makes sense there (My opinion, proof me wrong).
var Devices = BackboneCollection; var devices = ;devices;
You can add dynamic arguments in Collections by referencing object properties
var Devices = BackboneCollection; var devices = ;devices;
This call results in the following RPC request:
"jsonrpc":"2.0""method":"MeNotJava/getDevices""id":"1331724850010""params":"hello" "world" "arg3":
Content-Type
The default content type of requests is 'application/json' You can override it like this:
// ...rpc: contentType: 'application/json'//...
Namespaces
Most of the time, you´re in need to call methods within a namespace. No worries, we thought of that too.
var TextModel = BackboneModel; // Fetch a random text snippetvar textModel = ;textModel; // Will fire this request"jsonrpc":"2.0""method":"MySuperEnterprisyNamespace/getRandomTextSnippet""id":"1331724850010""params"::
By the way, you´re not tied to the default namespace separator, you can add you´re own easily:
var TextModel = BackboneModel; // Fetch a random text snippetvar textModel = ;textModel; // Will fire this request"jsonrpc":"2.0""method":"MySuperEnterprisyNamespace::getRandomTextSnippet""id":"1331724850010""params"::
Nice, hah?!
Exceptions
When working with a JSON RPC Service you can encounter different types of errors. The default error handler simply throws if something bad happens.
We have a predefined list of errors:
- 404: {code: -1, message: '404'}
- 500: {code: -2, message: '500'}
- typeMissmatch: {code: -3, message: 'Type missmatch'}
- badResponseId: {code: -4, message: 'Bad response ID'}
- noResponse: {code: -5, message: 'No response'}
Also, there´s always the possibility for setting custom errors. Due to the spec, this is done via an error property in the json response instead of an result property. Backbone.Rpc recognizes that errors and then triggers the error handler (as said, default one throws).
To prevent Backbone.Rpc from throwing errors, you can add you´re custom error handler.
var TextModel = BackboneModel;
Changelog
0.1.2
- Grunt fixes
- REST can now be used along with this plugin (Fixes #1)
- Collections can now have dynamic arguments in calls (Fixes #4)
- README improvements
- More tests
0.1.1
- Switch build system from cake to grunt
- Cleaned up
- Fixed #3 - Content type defaults to 'application/json' & can now be overriden
- Fixed #5 - README fixes & improvments
- Inline doc improvements
0.1.0
- Initial Release
License
Copyright (c) Sebastian Golasch (@asciidisco) 2012
The plugin is released under the MIT License. Feel free to add and/or modify it´s contents. Feel free to contact me if you have any questions.