3.2.0

AJAX-related: Howto use XMLRPC with activewidgets

Hi,

Since I could not find anything about XMLRPC, I thought you might be interested in this.

To be a "proper" Ajax application it comes in handy to use XMLRPC, and in fact there is really one major advantage over plain XMLHTTPRequests:
XMLRPC knows about simple types. Which includes integers, floats, boolean, lists = arrays, dictionaries = objects = associative arrays, binary and of course strings.

BTW: The server I use is Zope (http://www.zope.org)

Having a server that understands XMLRPC, you are able to call methods with typed parameters, thus making it possible to avoid writing your own marshalling and unmarshalling functions. (Un/Marshalling is the process of transforming simple types into XML and back. Actually marshalling is not limited to XMLRPC, it's for all protocols. JSON is an example for another suitable protocol.)

You can easily use XMLRPC with ActiveWidgets, too! [Ah! we're getting to the point finally.]

Here is an example using "jsolait" (a javascript "framework", which has a fairly stable xmlrpc client: http://www.jsolait.net).

But you might use "sarissa" as well - just a matter of taste, I suppose.

<!-- don't forget to load the jsolait library -->
<script type="text/javascript" src="jsolait/init.js"></script>

<script type="text/javascript">
// importModule is a jsolait function injected into the global namespace
// 'xmlrpc' is the jsolait xmlrpc library, as you might have guessed
var xmlrpc = importModule('xmlrpc');

// don't forget the '/' at the end
// for security reasons the server must be the same server which
// served this very page
var server = "http:my.server.com:my_port/some_url/";

// the method name
// do NOT supply parameters with method?arg1=foo&arg2=bar
var method = "my_method/maybe/with/a/path";
var get_data = new xmlrpc.XMLRPCMethod(server,method);


// Now you can use "get_data" XMLRPCProxyMethod to get the data.
// The arity of the function is variable, use as many parameters
// as the serverfunction expects.
// If the last parameter is a function, it will be used as callback, making
// the call an async one. 

// sync call example:
var result = get_data({id:'42',prop:['sample','values']},3.1428,false);

// where result may contain any simple type including javascript objects


// same as async call:
var result = get_data({id:'42',prop:['sample','values']},3.1428,false,callback);

// the callback must have two parameters
callback = function(result, error) {
  if (error) {
     alert(error); // the server returned an error, this is the msg
  } else {
     // do what you please with the result...
     // maybe you must convert the data-model?
     convert_model(result); 
     // or save the result in a global variable for reuse?
     globalServerModel = result;
     // or the server returned a fitting two dimensional array?
     myGrid.setProperty('data/text',result);
  }
}
</script>


I apologize I cannot give you a complete working example right now, due to the lack of a server _not_ behind a firewall. Since I'm working on a project to integrate ActiveWidgets into Plone (a Zope CMS, http://plone.org), I'll come up with an example - hopefully before my summer holiday ;)

Sorry for the 'Ajax' buzzword in the topic -- I could not resist. :-)
Sebastian Wiemer (NIONEX)
July 6,
Thanks for the XMLRPC tip. I've been working on (what is now called) AJAX since it's release.

Other than understanding types (eliminating marshalling) what other benefits are there?
AcidRaZor
July 6,
In JavaScript it's nice to have an object as result (which is only possible because of XMLRPC). The object might contain multiple values of different types. This is not that easy to do without XMLRPC.

Imagine a method on the server giving back the following result:

// *** snip
result.id = 'my_div_id';
result.id.innerHTML = '... some HTML code ...';
result.id2 = 'my_other_div_id';
result.id2.innerHTML = '... some other HTML code ...';

/// snap ****

The callback function can then update two (or any number) of div elements in your page simultaneously. So you make one call and get a refresh on several objects in your HTML page. This is important if you want to make an async call to the server, displaying a "busy" gif, a status message, clean up some content and then refresh it all together when the callback is called.

For Zope I've created a server-backend to ease the generation of javascript result objects. There is also a client-side library to automatically deal with the result object. It'll be released when it's feature complete (though it's already in use and prooved to be stable).


Other than that (back to your question) XMLRPC has a disadvantage: it is a very verbose format. Good for debugging, but a waste of bandwidth. JSON would be more efficient, but there are no JSON server in python I know of. (Only a JavaScript clients.)
Sebastian Wiemer (NIONEX)
July 6,
Thanks for the response.

If I understand you correctly, I can return mutliple objects with XMLRPC, but at cost of using up more bandwidth?

Would you know of any sites that shows a comparison to that? In the last 2 years I've developed an application that uses XMLHTTPRequest object. We have 3 div's, left menu and a top/bottom content. We're able to load multiple content pages within these 3 div's using what we've written. 3 calls get made basically.

What benefit would XMLRPC have for me? Sorry about these questions, just trying to figure out if XMLRPC is the best route we should take. I need to take into consideration the future of this project.

We're using mostly Javascript to do the calls and it's one of the reasons why I'm looking at this grid.

Ta
AcidRaZor
July 6,
The bandwidth consumption depends on the datastructure. The deeper the structure is marshalled, the more it takes to encode it in XMLRPC:
Here is an example (in python, just ignore the quotes for the property names):

Let's assume you have a three table layout. Clicking something in the navigation (left) ensues changes in the navigation, the content (middle) and a portlet (right).
You make one call issued by the navigation, and get the following return data-structure:

{
'left': {'innerHTML': '<table>....</table>', 'title': 'Navigation'},
'mainContentMiddle': {'innerHTML': '<table>....</table>',
                       'title': 'Welcome to my homepage'},
'right': {'innterHTML': '<table>...</table>', 'title': 'myportlet'}
}


This structrue could be transmitted as a server result. It ensures that the data of your tables in your three table design are in sync.

The bandwidth consumption is due to the XMLRPC marshalling, which looks like this:

<params>
  <param>
    <value>
      <array>
    <data>
      <value>
        <string>right</string>
      </value>
      <value>
        <struct>
          <member>
        <name>innterHTML</name>
        <value><string>&lt;table&gt;...&lt;/table&gt;</string></value>
          </member>
          <member>
        <name>title</name>
        <value><string>myportlet</string></value>
          </member>
        </struct>
      </value>
    </data>
      </array>
    </value>
  </param>
  <param>
    <value>
      <array>
    <data>
      <value><string>mainContentMiddle</string></value>
      <value>
        <struct>
          <member>
        <name>innerHTML</name>
        <value><string>&lt;table&gt;....&lt;/table&gt;</string></value>
          </member>
          <member>
        <name>title</name>
        <value><string>Welcome to my homepage</string></value>
          </member>
        </struct>
      </value>
    </data>
      </array>
    </value>
  </param>
  <param>
    <value>
      <array>
    <data>
      <value><string>left</string></value>
      <value>
        <struct>
          <member>
        <name>innerHTML</name>
        <value><string>&lt;table&gt;....&lt;/table&gt;</string></value>
          </member>
          <member>
        <name>title</name>
        <value><string>Navigation</string></value>
          </member>
        </struct>
      </value>
    </data>
      </array>
    </value>
  </param>
</params>


As you might already have realized: the bandwidth consumption depends on the data. If the HTML portions (here indicated with the property name "innerHTML" and of course shortened in the example!) are the big parts, so the XMLRPC overhead gets small in comparison. On the other hand, if you transfer associative arrays with thousands of property names and integer values, the overhead is huge compared to the unmarshalled data.

The advantage is, that you "know" what the metadata (the data about the data) is and can simply grab it from the result like getting the title from the innerHTML with:
"result.left.title"

Maybe the title is not a good example, you might think of ids, or expiration dates or whatever. It's not necessary to artificially integrate the metadata into the HTML content (i.e. forms, scripts, ...)


So again and in short:
1. the bandwidth consumption depends on the nature of your data, if it contains a small number of large chunks XMLRPC is your friend, if it contains a huge number of small chunks XMLRPC should either be avoided, replaced by JSON or used with gzip compression.
2. XMLRPC makes it easy to seperate metadata from contents
3. XMLRPC makes it possible to make one call and update "any number" of div/tables whatsoever on your page.

-- hope this helps

SW
Sebastian Wiemer (NIONEX)
July 7,
The link to jsolait.net is incorrect and should be http://jsolait.net/ ;)
Jan-Klaas Kollhof
March 2,

This topic is archived.

See also:


Back to support forum