Skip to content

Creating js files with Rhino (from JSON)

13-Nov-07

(This is primarily a note to myself)

I've been playing with Rhino. Specifically, reading in json objects, turning that into normal, runnable objects and saving that to a file so browsers can run it. More specifically, the code that transforms the JSON to an object in the browser should be exactly the same as the one that runs in Rhino. That way I don't have to maintain two different versions.

I'm working on an idea that requires reading in JSON objects and creating objects with methods and properties based on that JSON and could be normally done per request of the page. Obviously, if the JSON is pretty much static, it would be best if we could save the resulting object to a file and reference that file in our pages instead. It would save 1) the request for the JSON file and 2) processing to create the final object. There are two steps to do this.

  1. Transform the JSON
  2. Saving the object

Transform the JSON

Easy, enough. Iterate through the JSON object, create new object and add methods and properties to it as you see fit. To save it though you need a String representation of the object. Gecko's toSource() method helps there.

Saving the object

In Rhino, make use of Java's FileWriter object and save it to the filesystem. If your object is really simple then that's probably it and you'll be able to run the object in your browser. If your final object makes use of closures then you'll get errors, obviously, as the variables the closures have reference to, aren't being created at all when the code is run in the browser. Solution (when run in Rhino) is to turn those methods that use closures into strings and add the variables in via regexp or whatever and then eval it!! Remember, it's only done in Rhino, so it's only done once. One thing to note, you don't have to replace every occurence of that variable name, only the first one (or add a initialisation statement for that variable to the function). Now when the code is written out to file (and read back in by the browser) the variables will have a valid value.

For simple types, like String or numbers, this will work fine. For objects or arrays, you could use toSource() but that just dumps out a object literal of the object at that time and not a reference which is what you really need. The other thing is you'll have a large object dump in the final code which makes the final code much much larger than you need. The solution then is store these objects in an Array or manager object (outside this system) and retrieve them as needed within your final code.

Here's an example:

JavaScript:
  1. .
  2. .
  3. .
  4. o[sMethodName] = function(varA,varB){
  5.   var f = function(var1){
  6.    //Use of an objManager to retrieve object we need
  7.    //varA and varB have no value in Rhino
  8.    objManager.getObj(var1).method(varA,varB);
  9.   };
  10.   //so for rhino
  11.   if ((typeof this["load"] == "function") && (typeof this["Packages"] == "function")) {
  12.    //so get string version of function
  13.    var fString = f.toString();
  14.    //replace variable names with actual variable value.          
  15.    fString = fString.replace('varA', '"' + varA + '"');
  16.    fString = fString.replace('varB', '"' + varB + '"');
  17.    return eval(fString);
  18.  }
  19.  
  20.  return f;
  21.  
  22. }(a,b);
  23. .
  24. .
  25. .

There you go. Ugly, more than probably not robust but it's the only way I've found to do what I need to do for my use case; admittedly probably not a common usage scenario.

Is there a better way?

ActsAsUndoable

18-Jul-07

With web apps becoming more and more like Desktop apps, it seems like user interfaces need be more like desktop user interfaces too. Some of these web apps can have a complex UI and their users need to be able to feel comfortable with it. Of course, making the UI as simple as possible is key, but if a task is relatively complex then the UI will also be relatively complex. With more complex tasks, users can make mistakes or want to change things and if they do, they'd appreciate a way of doing so. One way to do that is to provide the user a way of undoing their actions; a way to retreat over their history. Just to make clear, this is something along the lines of a user interaction history, not a browser navigation history. Hence ActsAsUndoable, one way of adding undo functionality to your interactive widgets. (Incidentally while I was writing this post, Aza Raskin posted an article on A List Apart about using undo functionality in interaction design, which seems to dovetail well with this post.)

Design Patterns

Whenever I code a widget, there's two resources I look to. One is Yahoo!'s Design Pattern library and the other is Jennifer Tidwell's Designing Interfaces book. It's from this book and more specifically the explanation of the Multi-Level Undo pattern that ActsAsUndo is based on.

Basically the Multi-Level Undo pattern says that if users can navigate through their action history and undo their actions, then they can explore their own work paths quickly and safely. The most obvious desktop example of a navigable history is Photoshop's history panel.

The pattern states that these kind of actions should be undoable:

  • Text entry for documents or spreadsheets
  • Database transactions
  • Modifications to images or painting canvases
  • Layout changes -- position, size, stacking order,
    or grouping in graphic applications
  • File operations, such as deleting or modifying files
  • Creation, deletion or rearrangement of objects such
    as email messages or spreadsheet columns
  • Any cut, copy, or paste operation

There are apps like these available on the web and some do have some simple undo/history functionality. These do tend to be only a single step undo and then, only for actions that change and save a new state eg move to trash. But also other actions that users make but perhaps don't yet want (or need) to save should also be undoable and at a multiple level too. So, how do we as implement something like the Multi Level Undo interaction pattern? We use the Memento software design pattern.

Demos

Two of Jennifer's examples are text entry and stacking order changes. I thought these would be relatively simple examples to use for demo purposes. Here's the text entry demo and also the stacking order demo. I used the demo of the YUI's sortable list which I hope they don't mind. If you want, take a look at these to see whats going on before reading on.

Text entry

The first example I'll cover is the text entry one. It's a simple example of a textarea in which users can enter text and save snaphots. The original class has two properties el and sValue. el represents the textarea and sValue, the textarea's value. It has a method called setText() whichs sets sValue to the value of the textarea.

Finally we have a snapshotText() method which calls setText(). We wire a button element to this method.

JavaScript:
  1. YAHOO.NT.UI.TextUpdate = function(elId,sGroup,sPreviewId) {
  2.   this.el = document.getElementById(elId);
  3.   this.sValue = this.el.value;
  4. }
  5. YAHOO.NT.UI.TextUpdate.prototype.setText = function(sValue) {
  6.   this.sValue = this.el.value = sValue;
  7. }
  8. YAHOO.NT.UI.TextUpdate.prototype.snapshotText = function() {
  9.   if (this.sValue != this.el.value) {
  10.     this.setText(this.el.value);
  11.   }
  12. }

We can add undoable functionality by augmenting it with YAHOO.Acts.as.Undoable. This adds a sCaretakerGroup property and undo(),redo(),revert() and restore() methods. All we need to do is subscribe to the 'stateLoaded' event and make a call to saveState() of the Caretaker to record the initial state. We can do this in the constructor of out TextUpdate object or a init() method if we choose to use one.

JavaScript:
  1. this.sCareTakerGroup = sGroup;
  2. YAHOO.NT.CaretakerRegistry.subscribe(this.sCareTakerGroup,'stateLoaded',this.restore,this,true);
  3. YAHOO.NT.CaretakerRegistry.saveState(this.sCareTakerGroup,'New',{'args':[this.sValue],'execute':this.setText,'oScope':this});

The first line just sets up a property that allows us to identify a caretaker to manage our states (more on this later).

The second line subscribes to an event called 'stateLoaded' and sets the callback to our restore() method.

Then, the third line saves our initial state. We need to do this so the revert() method can revert to the initial state. The callback we specify here depends on your object

So now our TextUpdate class looks like this :

JavaScript:
  1. YAHOO.NT.UI.TextUpdate  = function(elId,sGroup,sPreviewId) {
  2.   this.el = document.getElementById(elId);
  3.   this.sValue = this.el.value;
  4.  
  5.   //Interact with caretaker
  6.   this.sCareTakerGroup = sGroup;
  7.   YAHOO.NT.CaretakerRegistry.subscribe(this.sCareTakerGroup,'stateLoaded',this.restore,this,true);
  8.   YAHOO.NT.CaretakerRegistry.saveState(this.sCareTakerGroup,'New',{'args':[this.sValue],'execute':this.setText,'oScope':this});
  9. }
  10.  
  11. YAHOO.NT.UI.TextUpdate.prototype.setText = function(sValue) {
  12.   this.sValue = this.el.value = sValue;
  13. }
  14.  
  15. YAHOO.NT.UI.TextUpdate.prototype.snapshotText = function() {
  16.   if (this.sValue != this.el.value) {
  17.      this.setText(this.el.value);
  18.     //saves value to caretaker
  19.     YAHOO.NT.CaretakerRegistry.saveState(this.sCareTakerGroup,null,{'args':[this.sValue],'execute':this.setText,'oScope':this});
  20.   }
  21. }
  22. //make undoable
  23. YAHOO.augment(YAHOO.NT.UI.TextUpdate,YAHOO.Acts.as.Undoable);

The last line adds the undoable functionality to the TextUpdate object. (see next code snippet)

But what's all this caretaker stuff? Well, the Memento software design pattern is an established pattern that helps to implement undo functionality. I touched on the Memento pattern in an earlier post about object-oriented Actionscript.

The Memento pattern has three classes; Originator, Caretaker and Memento. Basically using these three classes, the Memento pattern works likes this:

If an Originator wants its state or some of its state to be undoable or redoable, then it must save its state to a Caretaker. This Caretaker will manage the various states (Mementos) of our Originator. (isn't it lovely terminology?)

Using this as a premise, we can devise a simple 'framework' for adding multi level undo functionality to our apps. We don't need (or want) to create lots of class hierarchy for our apps but the only classes we need to create revolve around the Caretaker object. Each object that we need undo functionality for, we have a corresponding caretaker. To manage multiple Caretaker objects (since perhaps multiple objects need a separate history), we use a CaretakerRegistry singleton object to do so. This allows Caretaker objects to be registered and created, if not done so already. It also acts as proxy to caretaker objects as all calls to Caretakers are made via the CaretakerRegistry. A registry also allows multiple objects to monitor state changes of an Originator. See the HistoryList section for an example of such an object

Interaction is achieved using CustomEvents. Caretaker objects fire 'stateLoaded' and 'stateSaved' events. Originator objects subscribe to the 'stateLoaded event. Any other object that is interested in the state of our Originator will subscribe to both 'stateLoaded' and 'stateSaved' events. Each event passes the Memento object to each listening object.

Everytime the state of our object has changed and needs to be saved, we call the saveState method (see line 19) of our object's Caretaker which makes a note of the new state and fires off a 'stateSaved' event.

Here are the methods that ActsAsUndoable adds.

JavaScript:
  1. /**
  2. * redo changes
  3. */
  4.  undo : function() {
  5.     YAHOO.NT.CaretakerRegistry.loadState(this.sCareTakerGroup);
  6.  },
  7.  
  8. /**
  9. * Redo changes
  10. */
  11.  redo : function() {
  12.     YAHOO.NT.CaretakerRegistry.loadState(this.sCareTakerGroup,-1);
  13.  },
  14.    
  15. /**
  16. * Revert to initial text value
  17. *
  18. */
  19. revert : function() {
  20.     YAHOO.NT.CaretakerRegistry.loadState(this.sCareTakerGroup,0);
  21. },
  22.    
  23. /**
  24. *
  25. *
  26. * @param {Object} oState Object containing callback to call with specified
  27. * arguments and scope. Fields are :
  28. *
  29. * {Array}  oState.args Array of arguments to call callback with
  30. * {fn}        oState.execute Calblack function
  31. * {Object} oState.oScope Object to use as scope for callback
  32. */
  33. restore : function(oState) {
  34.   if (oState.execute) {
  35.     oState.execute.apply(oState.oScope,oState.args);   
  36.   }
  37. }

Our object also has undo(),redo(),revert() methods, all of which call the loadState() method of the Caretaker. This, in turn, fires off a 'stateLoaded' event. Because our originating object subscribes to the 'stateLoaded' event it is passed the Memento object, which represents the state of the object that it needs to be undone, redone or reverted to. The listening method of our object that the custom event fires to is called restore(). This is the method that sets the state of our object. The restore() method is passed an object with three properties. These are args,execute, and oScope and are defined when we save the state via the saveState() method. Our restore() simply calls the method specified in execute passing as args those specified in args using oScope as the scope for the method.. I restore the state of the object like this (via a method call) rather than simply overwriting some properties with older properties as often some logic needs to be run as well; just resetting the properties probably won't suffice in anything other than a very simple widget). The best way to do that is via existing methods on our originating object. For the pattern heads out there, this way is similar to the command pattern without actually creating Command objects - the existing methods are the Commands.

Stacking Order

The stacking order demo is similar. I rewrote the example to reflect the changes needed to make the reordering done by single method (orderLi). Also I haven't augmented it with ActsAsUndoable as I don't use the undo, redo or revert functionality in the UI. The source for YAHOO.example.DDApp is probably a good example to view if you want to see how to add undoable functionality without using augmentation.

History List

The History List object is one that listens to state changes of a given object and renders them in a list. It shows how other objects besides the Originator can monitor changes of state. Clicking on each item in the list, rolls back the state of that object to the state. You just initialise it with the id of the container and the CaretakerGroup that the object you're providing a history for is using.

Each link in the history list is a named anchor. However in the update() method, we stop the Event so the browser doesn't actually add it to its own history. We don't want the act of navigating through the history of our own actions within our task to interfere with the history of our browser.

We can create a new HistoryList object that monitors changes to our object by this :

JavaScript:
  1. hl = new YAHOO.NT.UI.HistoryList('hlistCont','textArea');

The first is the id of an element in which to render the history list. The second is the name of the caretaker group to monitor. The list is rendered to the document and any saves, reverts, undo etc are shown in this list.

Resources and notes :

  • The ActsAsUndoable was an interim tongue-in-cheek working name but I kinda like it. The Acts.as namespace is a bit overkill but it fits pretty well and will work out nicely in future things I want to post about.
  • Accessibility - we should set the tabindex of our textarea or list to -1 and focus() them when a history list item is clicked or pressed. See this making ajax work with screen readers article from Juicystudio
  • For the textUpdate example I've used the word 'snapshot' rather than 'save' as 'save' would probably mean save permanently to most people. Another button called save could easily be added that would do a true save via normal form functionality. It could even be done using AJAX and the Browser History manager from the YUI library, which would add an item to the history list. Having said that, we don't want to confuse user with two histories; browser history and what I call User Interaction History.

  • I used the terms as specified as in the Memento Design Pattern. These aren't the clearest names and I was in two minds of calling Caretaker and CaretakerRegistry, UserActionManager and UserActionManagerRegistry. But I suppose these objects can be used for things other than user actions so I kept the design pattern language.

You can download the examples and js files. One of these days I'll make my subversion repo public but for now old fashioned zip files will have to do.

Finally, thanks to Tony Kabalan for being a sound board and inputting some useful ideas.

AjaxEvent

16-Jul-07

Tim Huegdon has a great post about a really rather sweet piece of code called AjaxEvent over at his site, nefariousdesigns. Developed with Mark Aidan Thomas, AjaxEvent is an object that wraps around the YUI Connection and CustomEvents that makes managing multiple, distinct ajax calls really easy.

Another Tabbed Interface

15-May-07

This is a rather belated post and is sort of a continuation of my last post about Aspect Oriented Programming. I've made yet another tabbed interface widgety thing (like the 'tubes needs another one) that uses AOP to add additonal features. A tabbed interface widget provided a nice problem for me to experiment with AOP. You can see the results which allows tabs in a widget to be draggable and closeable too. Built with a dash YUI goodness of course.

The actual 'problem' wasn't actually anything to do with the core behaviour of a tabbed interface. After all, the mechanics of such a problem is pretty simple; hide one element, show another. No, I wanted to make the tabs draggable and closeable, much like an OS tab that can be seen in Firefox or Eclipse. Using the YUI library, making the tab draggable is relatively straight forward but it did result in some duplicated code which I didn't like. That was the 'problem'.

Essentially, it was like this: My original code had two objects, the YAHOO.NT.TabsModule and YAHOO.NT.Tab. The TabsModule was the managing object for each of the Tab objects. If I wanted to make it draggable I need Tab to extend YAHOO.util.DDProxy. No problem there except of course there has to be additonal logic in the Tab object to do so and also manage the dragging 'n' dropping. Subclassing Tab would have worked but again code would be duplicated in those methods that needed the changes. But then you get into the trouble of class trees. For instance, DraggableTab subclasses Tab and so does Closeable Tab. But what if I wanted a Draggable and Closeable Tab? That'd be a little trickier to do while still maintaining some sense of clean code.

The rather clean solution turns out to be AOP. Quickly, AOP allows us to easily add new code to existing code without editing it. It does this by essentially wrapping the original code so that the new code runs 'before','after' or 'around the original code. These are the so called 'aspects'. So it turns out that to make a Tab draggable I'd need to add new methods (my own as well as YAHOO.util.DDProxy) as well as fiddle with a few existing Tabs methods:

Here I've outlined which methods have been aspected (is that the right term?) and what the new code adds to the original.

  • YAHOO.NT.TabsModule.init is after aspected by both YAHOO.NT.DraggableTabs and YAHOO.NT.CloseableTabs - both adds a new CustomEvent which listens to all existing Tab instances

  • YAHOO.NT.TabsModule.selectTab is before aspected by YAHOO.NT.CloseableTabs - adds logic to detect to close tab.

  • YAHOO.NT.Tabs.initTab is after aspected by both YAHOO.NT.DraggableTabs and YAHOO.NT.CloseableTabs - adds new configuration logic, custom event creation

  • YAHOO.NT.Tabs.activateTab and YAHOO.NT.Tabs.deactivateTab are both after aspected by YAHOO.NT.CloseableTabs - adds logic to show/hide close icon.

Though, AOP in Javascript certainly isn't new, I really like the relatively clean way its allowed me to separate behaviours without duplicating any code.

JS Fun

25-Mar-07

For the last few months I've been playing around with different design patterns and methodologies in Javascript. I've been looking at the Composite pattern and also Aspects Oriented Programming (AOP).

AOP is a way of changing the behaviour of existing code without modifying it. It does this by providing, what AOP calls, advice at certain join points. In plain english, it provides a way of adding additional behaviour (advice) at certain points in your program (join points). For example, adding logging functionality to your code is a standard example. Generally, you don't want every method in your code to contain logging code. It's not really part of the core base code. AOP provides an easy way of doing without modifying your code. But because of the way AOP works, you can add as many behaviours as you want to, to any object.

What and how?

AOP provides three aspects called before, after and around. This means that you can add additonal behaviour before, after or around certain points in your code of your own choosing. I've created a static class called YAHOO.Abstract.Aspect that I use to add advices to other objects. It's a very simple one and just adds the three advices to an method.

JavaScript:
  1. YAHOO.Abstract.Aspect = function() {
  2.     aAspects = [];
  3.     aAspects["before"]=function(oTarget,sMethodName,fn) {
  4.         var fOrigMethod = oTarget[sMethodName];
  5.         
  6.         oTarget[sMethodName] = function() {
  7.           fn.apply(oTarget, arguments);
  8.           return fOrigMethod.apply(oTarget, arguments);
  9.         };
  10.     }
  11.     //after
  12.     aAspects["after"]=function(oTarget,sMethodName,fn){
  13.         var fOrigMethod = oTarget[sMethodName];
  14.         oTarget[sMethodName] = function() {
  15.             var rv = fOrigMethod.apply(oTarget, arguments);
  16.             return fn.apply(oTarget, [rv]);
  17.         };
  18.     }
  19.     //around
  20.     aAspects["around"]=function(oTarget,sMethodName,aFn){
  21.         var fOrigMethod = oTarget[sMethodName];
  22.         oTarget[sMethodName] = function() {
  23.               if (aFn && aFn.length==2) {
  24.                 aFn[0].apply(oTarget, arguments);
  25.                 var rv = fOrigMethod.apply(oTarget, arguments);
  26.                 return aFn[1].apply(oTarget, [rv]);
  27.               }
  28.               else {
  29.                 return fOrigMethod.apply(oTarget, arguments);
  30.               }
  31.               
  32.             };
  33.     };
  34.     return {       
  35.         advise : function(oTarget,sAspect,sMethod,fAdvice) {
  36.             if (oTarget && sAspect && sMethod && fAdvice && aAspects[sAspect]) {
  37.                 //decorate specified method
  38.                 aAspects[sAspect](oTarget,sMethod,fAdvice);
  39.             }
  40.             return oTarget;
  41.         }
  42.     }
  43. }();

For instance, if I wanted to add a before advice, I'd do something like the following :

JavaScript:
  1. YAHOO.Abstract.Aspect.advise(obj,'before','method',function() { alert('before')});

After advice is similar:

JavaScript:
  1. YAHOO.Abstract.Aspect.advise(obj,'after','method',function() { alert('after')});

Adding around advice is slightly different as you have to provide two methods, one for before and one for after:

JavaScript:
  1. YAHOO.Abstract.Aspect.advise(obj,'around','method',[function() {
  2.                 alert('before');
  3.                 },
  4.                 function() {
  5.                 alert('around');
  6.                 }]
  7. );

All arguments are passed transparently to the original methods and for all after methods, the return value of the original method is passed in.

Let's see how easy it is using the standard logging example. Its an simple but probably unpractical example.

This example add a simple logging behaviour for every method of a specified object. When a method is called, it is logged and so are its arguments. It also displays the methods return value, if any. For this example, it makes use of Firebug and some of its console functions, specificially group and groupEnd. These basically indent and outdent grouped console.log outputs. So how do we write the behaviour? Well, before a method is called, we want to start a new console group and also output which method was called and also any arguments if any were passed. Something like this:

JavaScript:
  1. function() {
  2. window.console.group('Entered method %s',sMName);
  3. window.console.log("Received arguments: %o",arguments);
  4. }

Then when a method has returned we want to log that the method has returned and any return value it may returned.

JavaScript:
  1. function() {
  2. window.console.log("Returned : %o",rv  || 'zilch');
  3. window.console.log('Exited method %s',sMName);
  4. window.console.groupEnd();
  5. }

In AOP terminology these would be termed "before" and "after" advice. But since there is also "around", we can use that instead so we only modify each method once.

So, the full code to add this logging behaviour to any object would be like this:

JavaScript:
  1. YAHOO.namespace('YAHOO.NT');
  2.     YAHOO.NT.trace = function(oTarget) {
  3.         for (var p in oTarget) {
  4.             if (typeof oTarget[p] == 'function') {
  5.                 (function (){
  6.                 var sMName = p; 
  7.                 var cnsl = window.console;       
  8.                     YAHOO.Abstract.Aspect.advise(oTarget,'around',sMName,[function() {
  9.                             cnsl.group('Entered method %s',sMName);
  10.                             cnsl.log("Received arguments: %o",arguments);
  11.                         },
  12.                         function(rv) {
  13.                             cnsl.log("Returned : %o",rv  || 'zilch');
  14.                             cnsl.log('Exited method %s',sMName);
  15.                             cnsl.groupEnd();
  16.                         return rv;
  17.                     }]);
  18.                 })()
  19.             }
  20.         }
  21.     }

The above code creates a new namespace so we don't pollute the global namespace and a new method called trace. All it does it receive a target object and adds the around advice to each method that it finds. It's also possible to extend this so that it receives another parameter which would state a whitelist or blacklist of methods to advise (or not). The actual call to advise any object, let's say the Dom object of YUI :

JavaScript:
  1. YAHOO.NT.trace(YAHOO.util.Dom)

You can see the output on the example page.

What else can AOP be used for?

  • Profiling - very similar to the trace, but instead maintains a timing of how long each method took.
  • Event firing on attribute changes - if you use getters and setters and when a set method has been called, automatically fire a valueChanged custom event. In practice, can really only be used when external entities change an objects property (Its not wise for an object to call its own setter method).
  • Validation of methods arguments - validate passed arguments to a method, specifically setter methods though any type of method can be used.
  • Convertors - bridge output from one object to another incompatible object
  • Provide an alternate to subclassing - use mixins instead of subclassing to add more and more behaviours while reducing amount of code duplication. I've used this for a widget and its really useful. I hope to be posting about that in a few days.

Is it useful?

I think it can be, in some cases. It means careful consideration about how you design your code, but I can envisage a small library using AOP or similar metaprogramming techniques. Often in larger javascript apps, there are many similar types of objects doing similar things. These are often utility objects which interact with different parts of your code but still have quite a lot of similarity within them. Why not use metaprogramming techniques to write these duplicated parts of your code using your own code as a base?

Where else is it used?

AOP in javascript isn't new to the Javascript world. Here's the post about aspects I first read about using JS late last year (and I've just noticed recently updated). It was Justin Palmer's post though that got me thinking about AOP in widgets. The examples there uses Beppu's ActsAsAspects class. There's no difference between between that one and mine in terms of functionality except Beppu's version adds a couple of things to the target object which I didn't want to do. Also Dojo uses it in its event classes.

Howdy..

19-Nov-06

Hey.

It's been a while.

Been busy with work, life and stuff.

But feel like posting again so I've changed servers and got a temp design up, which will change soon.

So let's see what happens.

Archives

18-Nov-06

Search

21-Mar-05

Webservices

18-Mar-05

The following list the webservices available at this site :

UK TV Webservices

These services provide UK TV and Radio listings for a seven day period.

SOAP version- LIVE

The SOAP version's signature can be seen by viewing its wsdl. Its request and response can be seen in action in the sample php client.

XMLRPC version- LIVE

There is also a XMLRPC version available. The messages page provide the exact response and request messages when using the service.

About Me

18-Mar-05

Hi, here's a little blurb about me and this blog.

My name is Lawrence Carvalho and I'm a web developer based in London, UK and have been since 1999. I currently work for Yahoo! Europe and this blog is here as an outlet for any personal projects/ideas I may be working on.
If you're curious about the name of the site, there was a good background to the ins and outs of the name but I've forgotten it now so it probably wasn't that good anyway.

I hate writing these 'about me' pages so I'll think I'll leave it like this for now.