Sending data and RPC to documents
Description: this page explains how to send targeted data and updates to loaded documents, and make RPC calls against them.
Each Gradient client may load and view multiple documents over one XMPP connection. These documents may come from more than one 'server' JID, and the path of each document may be different or the same. However, each document is uniquely identified by it's thread ID, as explained in the document loading page.
From the perspective of the client, each document is identified by three pieces of information:
The JID of the originating server. I'm calling this the "controller JID".
The path of the document, e.g. "/directory/index.svg".
The thread ID of the document.
Each document may only be updated by the server from which it originated. The server can send stanzas to the client JID, and can specify which document or set of documents the stanza is meant for.
Targeting using presence stanzas
Presence stanzas are generally broadcast to all subscribers for a particular JID. The Gradient client automatically subscribes to a JID before sending it a document request, and thereafter receives all presence broadcasts from that JID.
The client-side routing of the stanza is based on the presence or absence of a specific Gradient extension to XMPP, the "target-path" extension.
Below is a presence stanza sent from the example application. Highlighted is the target-path extension:
<presence from='gradient-examples@jabber.org/gradient' id='y7YB1-4' to='ian.s@jabber.org/squiggle'>
<gradient:target-path path='/svg/rectangles.svg' xmlns:gradient='http://ex-337.net/xmlns/xmpp/gradient'/>
<gradient:directive-set xmlns:gradient='http://ex-337.net/xmlns/xmpp/gradient'>
<directive appendto='/svg:svg' xmlns:svg='http://www.w3.org/2000/svg'>
<rect y='56' fill='none' height='50' stroke='black' stroke-width='2' width='50' x='94'
xmlns='http://www.w3.org/2000/svg' />
</directive>
</gradient:directive-set>
</presence>
The extension is simple: it contains one "path" attribute that specifies the document path the enclosed directive is meant for.
Upon receiving this presence stanza, the Gradient client checks for any documents that were loaded from gradient-examples@jabber.org/gradient, and has a path matching /svg/rectangles.svg. The directive is then applied to all documents that match these criteria.
In the absence of a target-path extension, the directive is be applied to all documents loaded from the sender, in this case gradient-examples@jabber.org/gradient.
If the presence stanza contains elements other than the directive-set and target-path extensions, and the document declares a processPresence function, then that function is called with an array of those elements as an argument. Trapping XMPP events is explained in further detail elsewhere.
Targeting using message stanzas
Message stanzas are sent from one JID to another, and could be considered a reliable unicast mechanism.
Messages may include a target-path extension just like a presence stanza, in which case any directive within the message is applied to all documents with that path for that client.
Messages may also specify a thread ID, which is done using the standard <thread/> element. In this case, the messages is applied only to the document with that thread. If no document with that thread ID exists, a 404 error is returned.
If the message contains elements other than a thread, a directive-set or a target-path extension, and the document declares a processMessage function, then that function is called with an array of those elements as an argument. Trapping XMPP events is explained in further detail elsewhere.
Sending IQ stanzas to documents
IQ stanzas are a different to message and presence stanzas because they contain one child element and expect a child element in response. In this way they could be considered as a free-form RPC mechanism, and are used for RPC between documents and servers, among other things.
Each document only accepts RPC calls from the server it was loaded from. There's no constriction on what can be put through RPC. However, for the server to make RPC calls against a document, it has to specify a thread ID. This is done using a namespaced attribute on the child element, like so:
<iq id="jcl_23" to="ian.s@jabber.org/squiggle" type="get">
<query xmlns="http://foo.com/bar/baz"
gradient:thread="a71effbfff6ff587c4e572d944f7cd525280fc3d23be4bb1"
xmlns:gradient="http://ex-337.net/xmlns/xmpp/gradient">
<elements for="example">
<or xmlns="what:ever" attitude="laissez-faire" />
text, if you prefer.
</elements>
</query>
</iq>
This tells the client which document to make the RPC call against. If the document specified by the above thread implements processIQ, then that function is called.
If a script error occurs, or if the script does not return an element, then a 500 error code is returned.
If the document does not implement processIQ, then a 501 (not implemented) error is returned.
Stanza routing - graphical illustration
Since the client stanza routing for presence, message and IQ stanzas follow a certain logic, the process by which the target documents are chosen can be displayed as a selection process.
Never one to avoid coloured boxes and labelled arrows if I can help it, the process is illustrated as a flowchart, available in several formats. Behold the power of yEd.
- Gradient Client stanza routing:
- As an image - JPEG - (116 Kilobytes)
- Vector graphics - SVG - (34 Kilobytes)
- Original yEd file - (3 Kilobytes)
To view the SVG version you'll need either a browser plugin from Adobe or Corel, the Croczilla version of Mozilla (not guaranteed to work), Batik Squiggle or the Gradient client, which is based on Squiggle.
© 2006. Some rights reserved. Author: Ian Sollars.