Pluggable Web Services with SMD

By on March 19, 2008 7:11 am

We have been leading the efforts in the development of Service Mapping Description (SMD). SMD is a flexible format and can be used to describe JSON-RPC, REST, JSONP, and other web services. SMD will provide a foundation to facilitate a future of pluggable interoperable SOA-based web services, where client and server components can be decoupled. Existing client/server frameworks tend to have tightly coupled communication, and applications built with standalone JavaScript libraries like the Dojo Toolkit generally must build their own client and server communication with the only assistance in the form of Ajax wrappers. With SMD, web services can be described with an open format, and client libraries can utilize these SMD descriptions to build high-level friendly communication wrappers. Of course, the Dojo Toolkit has taken the lead with the new SMD implementations in the Dojo Toolkit 1.1, but with SMD-based web service interaction, there is no lock-in. This provides an open definition of web services: any client and server can participate in providing or consuming these web services.

We have also been working on a specification for JSON Schema which provides the definition of contractual type constraints. JSON Schema is a definition for describing a valid set of values. Defining type constraints provides a standardized form of data documentation that can be used for data persistence, form generation, and creating contracts on data used in web services. SMD uses JSON Schema to describe the acceptable values for the all the parameters and return values of the available web services. With a shared vocabulary of data type definitions, SMDs can not only define what types of services are available, but can provide meaningful expectations on the type of data that should be passed to a service and what will be returned from it. With open comprehensive service description, servers can provide web services like JSON-RPC and bi-directional REST services like that of CouchDb and Persevere. These RPC and database storage services can be effortlessly integrated with JavaScript libraries which can become first-class citizens in high-level client/server application development instead of just animation providers. And with new (in the Dojo Toolkit 1.1) and upcoming (in the Dojo Toolkit 1.2) dojo.rpc and capabilities, the Dojo Toolkit can be more than just a library—it can be a fully capable front-end for client/server application development. Web services and data storage endpoints can be exposed by servers, and with minimal effort Dojo Toolkit users can connect and utilize these services without building custom communication handlers. Let’s take a look at how we can define services with an example SMD:

{target:"/jsonrpc", // this defines the URL to connect for the services
 transport:"POST", // We will use POST as the transport
 envelope:"JSON-RPC-1.2", // We will use JSON-RPC
 services: {
   add : { // define a service to add two numbers
   parameters: [
     {name:"a",type:"number"}, // define the two parameters
 foo : {   // nothing is required to be defined, all definitions are optional.
   //This service has nothing defined so it can take any parameters 
  //and return any value
 getNews : {
   // we can redefine the target, transport, and envelope for specific services
   target: "/newsSearch",
   transport: "GET",
   envelope: "URL",
   parameters:[ { name: "query", type: "string", optional: false, default: "" } ],

This SMD provides a definition for a variety of available services, and documents what parameters are expected, how to call the services, and what to expect in return. This SMD could be published by the server, and the client could retrieve the SMD by URL:

var services = new dojox.rpc.Service("");

Or alternately the SMD can be defined inline:

var mySMD = {target:"/jsonrpc"...};
var services = new dojox.rpc.Service(mySMD);

The dojox.rpc.Service will generate a services object that maps JavaScript methods to web services. To use the services object we can simply call the methods on the object. Note that that when these methods are called they return a dojo.Deferred object so that the service can be executed asynchronously. Here is an example of calling a service mapped method and retrieving the result when it is finished:

var newsDeferred = services.getNews({query:"dojo"});
newsDeferred.addCallback(function(returnValue) {
    alert("A news item: " + returnValue[0]);

This would trigger a request to “/newService?query=dojo” to retrieve the latest news. When the response is received back from the server, the callback function would be called and a news item would be retrieved. Thus we have successfully leveraged the SMD mechanism for decoupling the action of getting the news from the transport details.

The SMD-based architecture is another great example of the Dojo Toolkit philosophy of “build with, not on”. Every layer in the Dojo Toolkit is intended to be open, comprehensible, and extensible. This means your Ajax applications can use remote communication built on manageable reusable services with SMD, rather than relying on custom or black box communication techniques. With SMD there is no lock-in to the Dojo Toolkit: the SMD services can easily be created and consumed by any agents or libraries.