picture of Luis Argerich

What is the Web of Services?

There're a lot of comments in the market about "The web of services" from the simple ways of content syndication used today to the futuristic approach of UDDI. In its creation, the web was a collection of documents, browseable information. As the web evolved it was good to add some services to the web. In the future, the web will be the place where organizations provide services useful to the consumer and/or other organizations. This synergy between b2b and b2c models can be thought as a web of services.

What Services?

One big question is what kind of services can be provided on the web? Well, a lot of them, some are already in use and some will be appearing in a short future. Just to be illustrative, this is a short list of services:

How to Provide Services?

The big question is which is the proper way for organizations to provide services over the web? Today, some services are offered with an HTML interface. They are using documents to provide services, but what lies behind the service's interfaces? Web browsers are not alone in the race to conquer the web, cell phones, palmtops, handhelds, devices such as microwave ovens, sewing machines and applications from other companies want to access the web, query databases, convert data, pull information, etc. There should be a layer below the presentation level enabling the real web of services.

Enter XML.

XML is perhaps the strongest standard of the decade. XML vocabularies are the building stones that organizations will use to construct a universe of services. XML_RPC is a standard that will have to be studied to construct the web of services because it is useful to put services available on the web and because it is a solid standard that might easily get adopted. The importance of a standard to provide services is enormous for b2b services, companies sharing a common standard can grow very fast by using services provided by other companies and so on. I can't imagine a true web of services based on different propietary formats. They must find a standard to adopt.

XML_RPC a Standard for Distributed Processing.

XML_RPC is a standard for distributed processing over the internet. RPC: remote procedure call is a mechanism to launch procedures that may exist in different machines and be programmed in different languages. This is the key paradigm of distributed processing. In a distributed processing environment we can, for example, find a calculator software that runs the adding and substracting operations in different machines, the adding operation might be programmed in APL in a RS6000 machine and the substraction in "C" in a Unix Host. Other developers building distributed calculators can also use this "distributed" procedures or choose better ones. In RPC the key components are "procedures", servers provide procedures that the clients can call. Procedures might receive paremeters and return values. XML_RPC implements the RPC mechanism by using an XML vocabulary for passing and receiving data and the HTTP as the protocol carrier. XML_RPC servers accept XML_RPC requests and return XML_RPC responses. XML_RPC clients send XML_RPC requests and accept XML_RPC responses. They must decode the response and provide the answer in the way they want.

The XML_RPC Protocol.

The complete XML_RPC specification can be found in http://www.xmlrpc.com/spec. This is a summary:
The XML_RPC request.
It should be a HTTP POST request, the body of the request will be in XML, the format of the XML part of the request is:
<?xml version="1.0" ?>
<methodCall>
  <methodName>examples.getStateName</methodName>
  <params>
     <param>
        <value><i4>41</i4></value>
     </param>
  </params>
</methodCall>
The URI where data should be posted is not specified, it may be "/" for example if the whole server is dedicated to RPC processing. The payload is in XML, a single "methodCall" structure. The "methodCall" must contain a "methodName" sub-element, a string containing the method to be called. It is entirely up to the server to decide how to interpret the characters in "methodName". For example it could be the name of a file to excute, the name of a row in a database, or anything else. If the procedure receives parameters the "methodCall" may contain a "params" element with 1 to N "param" sub-elements, each "param" element may have a value with a type indicator that can be:
<i4> or <int>four-byte signed integer -12
<boolean> 0 (false) or 1 (true) 1
<string> ASCII string hello world
<double> double-precision signed floating point number -12.214
<dateTime.iso8601> date/time 19980717T14:08:55
<base64> base64-encoded binary eW91IGNhbid0IHJlYWQgdGhpcyE
Structs:
A value may also be a struct:
A <struct> contains <member>s and each <member> contains a <name> and a <value>.
Here's an example of a two-element <struct>:
<struct>
   <member>
      <name>name</name>
      <value><string>John</string></value>
      </member>
   <member>
      <name>age</name>
      <value><i4>19</i4></value>
      </member>
</struct>
<struct>s can be recursive, any <value> may contain a <struct> or any other type, including an <array>, described below.
<array>s
A value can also be of type <array>.
An <array> contains a single <data> element, which can contain any number of <value>s.
Here's an example of a three-element array:
<array>
   <data>
      <value><boolean>0</boolean></value>
      <value><i4>9</i4></value>
      <value><string>Hello</string></value>
   </data>
</array>
<array> elements do not have names.
You can mix types as the example above illustrates.
<arrays>s can be recursive, any value may contain an <array> or any other type, including a <struct>, described above.

The XML_RPC responses.

The XML response is a HTTP response content-type: text/xml with the body following the format:
<?xml version="1.0"?>
<methodResponse>
   <params>
      <param>
         <value><string>South Dakota</string></value>
      </param>
   </params>
</methodResponse>
<methodResponse> may have a <params> structure or a <fault> structure as sub-elements depending on the sucess or not of the procedure call. The params structure is the same as in the XML request, a <fault> element follows this syntax:
<fault>
      <value>
         <struct>
            <member>
               <name>faultCode</name>
               <value><int>4</int></value>
            </member>
            <member>
               <name>faultString</name>
               <value><string>Too many parameters.</string></value>
            </member>
         </struct>
      </value>
</fault>

The Web of Services Using RPC.

As you can see the web of services may easily be constructed using XML_RPC, organizations must deploy XML_RPC servers for different services provided by the company, client users, client software or client organizations can use this services to build higher-level services or applications for the end-user. The competition to provide more efficient, cheaper and better services will improve in a big way the quality of applications the user receives.
There're some issues not solved, for example how to catalog/index/search for services in the web? UDDI tries to solve this problem but is not a simple standard and the reaction of the industry to it is still unknown. The use of XML_RPC inside your organization can improve code-reusability and generate a new philosphy of distributed programming that can be a key knowledge in the following years. The evolution of XML_RPC from a very good way to solve distributed processing to be the basic layer of the web of services will have to be followed closely by people interested in this standard, meanwhile let's see XML_RPC in action!
Using XML_RPC from PHP.
PHP is a wonderful language to provide web services, we write the PHP code and then just place it where it has to be and we have a URL "callable" service. The implementation of XML_RPC from PHP may or may not be complex but there will be many to choose from. I have an XML_RCP extension in my next_PHP wishlist. In this article I'll be using "Useful Information Company's" implementation of XML_RPC by Edd Dumbill, you can download the code and documentation from http://xmlrpc.usefulinc.com.
There're two files containing base classes:
xmlrpc.inc classes needed for XML_RPC php clients.
xmlrpcs.inc classes needed for XML_RPC php servers.

Writing Clients.

Writing a XML_RPC client implies:
Take a look at this example:

<?php

$f
=new xmlrpcmsg('examples.getStateName',
               array(new 
xmlrpcval(14"int")));
$c=new xmlrpc_client("/RPC2""betty.userland.com"80);
$r=$c->send($f);
$v=$r->value();
if (!
$r->faultCode()) {
    print 
"State number "$HTTP_POST_VARS["stateno"] . " is " .
    
$v->scalarval() . "<BR>";
    print 
"<HR>I got this value back<BR><PRE>" .
    
htmlentities($r->serialize()). "</PRE><HR>\n";
} else {
    print 
"Fault: ";
    print 
"Code: " $r->faultCode() . 
    
" Reason '" .$r->faultString()."'<BR>";
}

?>
In the example we create a XML_RPC message to call the "examples.getStateName" method and we pass an integer parameter of type "int" with the number 14. Then we create the RPC client indicating the URL to call (path,domain and port). Then we send the message, receive a response object and check for errors. If no errors are found we display the result.
Functions to program RPC clients:
A client is created with:
$client=new xmlrpc_client($server_path, $server_hostname, $server_port);
And the method to send a message is:
$response=$client->send($xmlrpc_message);
It returns and instance of xmlrpcresp. The message that we pass is an instance of xmlrpcmsg which is created in the following way:
$msg=new xmlrpcmsg($methodName, $parameterArray);
Method name is the name of the method (procedure) to call, parameter array is a simple php array of xmlrpcval objects. For example:
$msg=new xmlrpcmsg("examples.getStateName",
		  array(new xmlrpcval(23, "int")));
An xmlrpcval object may be created using this forms:

<?php

$myVal
=new xmlrpcval($stringVal);
$myVal=new xmlrpcval($scalarVal"int" "boolean" "string" "double" "dateTime.iso8601" "base64");
$myVal=new xmlrpcval($arrayVal"array" "struct");

?>
The first creates a xmlrpc string value, the second creates a scalar value indicating value and type, the third one may be used to create complex objects by grouping other xmlrpc vals in structures such as arrays or structures as following:

<?php

$myArray
=new xmlrpcval(array(
              new 
xmlrpcval("Tom"), new xmlrpcval("Dick"),
              new 
xmlrpcval("Harry")), "array");

          
$myStruct=new xmlrpcval(array(
              
"name" => new xmlrpcval("Tom"),
              
"age" => new xmlrpcval(34"int"),
              
"geek" => new xmlrpcval(1"boolean")), "struct");
?>
The response object is of type xmlrpcresp and is obtained calling the method "send" from a client object, in a server you can create an xmlrpc resp using:
$resp=new xmlrpcresp($xmlrpcval);
In the client you use the method:
$xmlrpcVal=$resp->value();
To get the xmlrpcval from the response. Then you can use this method to get a PHP variable representing the response:
$scalarVal=$val->scalarval();
There're two useful functions to deal with complex types:
These functions reside in xmlrpc.inc.
$arr=xmlrpc_decode($xmlrpc_val);
Returns a PHP array stuffed with the values found in the xmlrpcval $xmlrpc_val, translated into native PHP types.
$xmlrpc_val=xmlrpc_encode($phpval);
Returns an xmlrpcval populated with the PHP values in $phpval. Works recursively on arrays and structs. Note that there's no support for non-base types like base-64 values or date-times.
Writing clients is a easy task in PHP, you can build web-based clients for XML_RPC services using PHP.

Writing Servers.

Building a sever is really easy with the classes provided by useful inc, you have to create a server by instantiating a constructor this way:

<?php

$s
=new xmlrpc_server( array("examples.myFunc" =>
                array(
"function" => "foo")));
?>
What you pass to the constructor is an asociative array of asociative arrays. The array have as keys the name of the methods to implement, each method has as key an array indicating with key "function" the name of a function to call for the method. In the example the procedure "examples.myFunc" calls function "foo", foo will be called a method handler for this reason.
Writing method handlers.
A method handler is easy this is a skeleton:

<?php

function foo ($params
{
    global 
$xmlrpcerruser// import user errcode value

    // $params is an Array of xmlrpcval objects
    
    
if ($err
    {
          
// this is an error condition
          
return new xmlrpcresp(0$xmlrpcerruser+1// user error 1
          
"There's a problem, Captain");
    } 
    else {
          
// this is a successful value being returned
          
return new xmlrpcresp(new xmlrpcval("All's fine!""string"));
    }
}

?>
As you can see you just check for errors and return an error (starting from $xmlrpcerruser+1) or a xmlrpcresp if everything went ok, all the rest of the wor is done by the class.

A sample XML_RPC Client and Server.

In this silly (really) example we build a server that given a number "n" returns "n*2", and a client that uses the method to determine "5*2" WOW!
The server:

<?php

include("xmlrpc.inc");
include(
"xmlrpcs.inc");


function 
foo ($params
{
    global 
$xmlrpcerruser// import user errcode value
    // $params is an Array of xmlrpcval objects
    
$vala=$params->params[0];
    
$sval=$vala->scalarval();
    
$ret=$sval*2;
    return new 
xmlrpcresp(new xmlrpcval($ret"int"));
}


$s=new xmlrpc_server( array("product" => array("function" => "foo")));

?>
The client:

<?php

include("xmlrpc.inc");

if (
$HTTP_POST_VARS["number"]!=""
{
    
$f=new xmlrpcmsg('product',
    array(new 
xmlrpcval($HTTP_POST_VARS["number"], "int")));
    
$c=new xmlrpc_client("/xmlrpc/servfoo.php""luigi.melpomenia.com.ar"80);
    
$c->setDebug(0);
    
$r=$c->send($f);
    
$v=$r->value();
    if (!
$r->faultCode()) 
    {
        print 
"Number "$HTTP_POST_VARS["number"] . " is " .
        
$v->scalarval() . "<BR>";
        print 
"<HR>I got this value back<BR><PRE>" .
        
htmlentities($r->serialize()). "</PRE><HR>\n";
      } 
    else 
    {
        print 
"Fault: ";
        print 
"Code: " $r->faultCode() .
        
" Reason '" .$r->faultString()."'<BR>";
    }
}
print 
"<FORM  METHOD=\"POST\">
<INPUT NAME=\"number\" VALUE=\"${number}\"><input type=\"submit\" value=\"go\" name=\"submit\"></FORM><P>
enter a number"
;

?>

Conclusions.

There's lot of infraestructure work to make the web of services XML_RPC enabled, there must be a catalog or indexing mechanism for distributed procedures and better interfaces to handle XML_RPC from programming languages, perhaps a XML_RPC PHP extension will do the work. There will be lot of news about XML_RPC and the web of services in the future, we'd better watch.
--Luis