var client = new XMLRPCClient('rpc_server.php');
if (! client.aqquireFunctions()) { // incase the call to system.listMethods fails
client.addFunction('strlen'); // add a function by name
var strlen = new XMLRPCFunction('strlen');
client.addFunction(strlen); // add a XMLRPCFunction object
}
try {
var len = client.strlen('i am a string');
} catch (response) {
/* function returned some kind of fault */
var code = response.getFaultCode();
var description = response.getFaultDescription();
}
client.onresponse = function(response) // set a response handler for all functions
{
var functionName = response.getCaller().gtFunctionName(); // get the name of the function that made the call
}
client.getFunction('strlen').onresponse = function(response) // set a response handler for an individual function
{
if(! response.isFault()) {
var returnVal = response.getReturnValue().getValue();
}
}
client.strlen(); // the function will now be called asynchronously
/* initializes the environment and sets up all variables - called on the onload event of the document body */
function init()
{
/* close the document output*/
document.close();
try {
emailValidator = new XMLRPCClient('email_validate.php');
} catch (e){
return;
}
emailValidator.aqquireFunctions();
emailValidator.getFunction('emailValidator_validate').onresponse = validateCallback;
emailValidator.getFunction('emailValidator_verify').onresponse = verifyCallback;
/* initialize global variables */
theForm = document.getElementById('formEmail');
btnSubmit = document.getElementById('btnSubmit');
txtEmail = document.getElementById('txtEmail')
verify = document.getElementById('verify')
verifyMsg = document.getElementById('verifyMsg');
txtVerify = document.getElementById('txtVerify');
btnVerify = document.getElementById('btnVerify');
emailMsg = document.getElementById('emailMsg');
/* disable the submit button */
btnSubmit.setAttribute('disabled', 'disabled');
txtEmail = document.getElementById('txtEmail');
/* set the onchange event of the email input box to the validateAddress() function */
txtEmail.onchange = validateAddress;
}
The validateAddress function is executed when the text contained in the email address field is changed. It executes the emailVlaidate.validate RPC. The response is handled by the validateCallback function which first checks that the response is not a fault. It then loads the two items in the return value: the validation result and the email ID into two variables.
Javascript:
function validateAddress()
{
var email = theForm.email.value;
var id = parseInt(theForm.email_id.value);
startupState(); // set initial state
if (email != ' ') {
// execute RPC - if an email ID is present, send that too
if (id) {
emailValidator.emailValidator_validate(email, id);
} else {
emailValidator.emailValidator_validate(email);
}
} else {
return;
}
}
function validateCallback(response)
{
if (response.isFault()) { // if a fualt occured - something strange happened; disable
btnSubmit.removeAttribute('disabled');
txtEmail.onchange = null;
verify.style.display = 'none';
return;
}
var emailID = response.getReturnValue().getValue().email_id;
var validated = response.getReturnValue().getValue().validated;
if (validated) {
emailMsg.style.display = 'none';
verify.style.display = 'inline';
verifyMsg.innerHTML = '<b>An Email containing your verification code has been sent to this address. Please Enter it before continuing.</b>';
theForm.email_id.value = emailID;
} else {
verify.style.display = 'none';
emailMsg.innerHTML = '<b>You have entered an invalid email address. Please correct it before continuing.</b>';
emailMsg.style.display = 'block';
}
}
The checking of the verification code is handled by the verifyAddress and verifyCallback functions. The verifyAddress function is executed when the verify button on the form is pressed. It executes the emailValidator.verify RPC which it passes the email ID and verification code typed by the user. The response is received by the verifyCallback function. Notice here how the fault code is checked, as the RPC may return one of several possible faults:
Javascript:
function verifyAddress()
{
var v_code = theForm.v_code.value;
var id = parseInt(theForm.email_id.value);
if (v_code == ' ') {
alert('No Verification Code Entered');
theForm.v_code.focus();
return;
}
emailValidator.emailValidator_verify(id, v_code);
}
function verifyCallback(response)
{
if (response.isFault()) {
switch (response.getFaultCode()) {
case -102: // email ID is invalid - clear and revalidate
theForm.email_id.value ='';
case -101: // email is not validated
validateAddress();
break;
default:
btnSubmit.removeAttribute('disabled');
txtEmail.onchange = null;
verify.style.display = 'none';
}
return;
}
var v_code = theForm.v_code.value;
if(response.getReturnValue().getValue()) { // successful verification
btnVerify.setAttribute('disabled', 'disabled');
txtVerify.setAttribute('disabled', 'disabled');
btnVerify.innerHTML = '<i>Verified</i>';
verifyMsg.innerHTML = '';
btnSubmit.removeAttribute('disabled');
return new XML_RPC_Response(new XML_RPC_Value(''), '-101', 'Email not validated.');
verifyMsg.innerHTML = '<b><i>' + theForm.email.value + '</i></b>';
theForm.email.value = '';
} else {
verifyMsg.innerHTML = '<b>Verification Failed</b>';
}
}
Again, drawing comparison between the original Ajax validation engine and the RPC version, you'll notice that the code is a lot cleaner and easier to understand.
XML-RPC simplifies the creation of distributed applications by providing a standard interface by which developers can use to call procedures on remote machines. The very concept of RPC and similar technologies fits in with one of the core objectives of all modern day programming languages: Code Reuse. Why create your own search facility, when Google does it better? Why implement your own blogging system, when several sites provide it for you? The adoption of these XML-based services including RSS, ATOM and RPC by large corporations such as Google and Microsoft is testament to the fact the web is evolving.
Before using XML-RPC, it is worth noting that it is not without it drawbacks:
Our next article is going to delve deeper in the world of RPC by taking a look at how SOAP and WSDL are used to completely automate RPCs at the two endpoints and how they serve to describe complex data types and the operations that can be carried out on them.