WSO2 has announced the release of WSO2 Mashup Server 1.5.2. This release introduced the support for Data Services (Exposing Database, Excel sheet, CSV as a service), Open ID Logins and personalized dashboards to manage mashups and some security improvements. Just have a look at the release note for all the details about the new features, fixes of the release.

WSO2 Mashup Server enables you to develop your enterprise mashups very easily. You will write your code for the mashups in javascript with the full help of integrated javascript objects to consume Web services or Atom feeds, manage sessions, scrape web pages and manipulate storage. Once your put your .js file in to the mashup server repository, your services automatically will have the WSDLs, ‘Try It’ functionality and SOAP, REST interfaces.

If you are new to Mashup Server or to develop Mashups, just have a look at the series of screenshots released by WSO2 sometime ago. That will no doubt take you from zero knowledge to a comfortable state to write full-fledged mashups.

February 10th, 2009WSO2 Carbon Products Released

WSO2 announced the release of the revolutionary series of products introducing a componentized design to implement SOA in cost effective and simple manner.

  1. WSO2 Web Services Application Server (WSAS) – WSO2 WSAS is an enterprise ready web services engine based on Apache Axis2. It is incorporated with many features including,
    • Data services support – Expose you enterprise data as a services in a jiffy
    • WSAS IDE – Eclipse IDE integration
    • Clustering support for High Availability & High Scalability
    • Full support for WS-Security, WS-Trust, WS-Policy and WS-Secure Conversation and XKMS
    • EJB service provider support – Expose your EJBs as services
    • Axis1 backward compatibility – Deploy Axis1 services on WSAS & Engage advanced WS-* protocols in front of legacy services
    • JMX & Web interface based monitoring and management
    • WS-* & REST support
    • GUI, command line & IDE based tools for Web service development
  2. WSO2 Enterprise Service Bus (ESB)- WSO2 ESB is a lightweight and easy-to-use Open Source Enterprise Service Bus based on Apache Synapse. Here is the listing of some of key features,
    • Proxy services – facilitating transport, interface (WSDL/Schema/Policy), message format (SOAP 1.1/1.2, POX/REST, Text, Binary), QoS (WS-Addressing/WS-Security/WS-RM) and optimization switching (MTOM/SwA).
    • Non-blocking HTTP/S transports based on Apache HttpCore for ultrafast execution and support for thousands of connections at high concurreny with constant memory usage.
    • Built in Registry/Repository, facilitating dynamic updating and reloading of the configuration and associated resources (e.g. XSLTs, XSD, JS, ..)
    • Easily extended via custom Java class (mediator and command)/Spring mediators, or BSF Scripting languages (Javascript, Ruby, Groovy, etc.)
    • Built in support for scheduling tasks using the Quartz scheduler.
    • Load-balancing (with or without sticky sessions) /Fail-over, and clustered Throttling and Caching support
    • WS-Security, WS-Reliable Messaging, Caching and Throttling configurable via (message/operation/service level) WS-Policies
    • Lightweight, XML and Web services centric messaging model
    • Support for industrial standards (Hessian binary web service protocol/Financial information exchange protocol)
    • Enhanced support for the VFS/JMS/Mail transports
    • Support for message splitting and aggregation using the EIP
    • Database lookup and store support with DBMediators with reusable database connection pools
    • JMX monitoring support
  3. WSO2 Registry – WSO2 Registry is a user-friendly, but comprehensive enterprise resource / metadata management solution. It is capable of
    • Storing and managing arbitrary resources and collections
    • Tagging, commenting and rating
    • Managing users and roles
    • Authentication and authorization on all resources and actions
    • Resource / collection versioning and rollback
    • Advanced search capabilities – tags, users, etc.
    • Built in media type support for common types (WSDL, XSD)
    • Dependency management – maintain relationships between dependent resources
    • Pluggable media type handlers for handling custom media types
    • Support for processing custom URL patterns via pluggable URL handlers
    • Support for custom query languages via pluggable query processors
    • Activity log and filtering support for the activity logs
    • Atom Publishing Protocol (APP) support for reading/writing the data store remotely
    • Subscribe to directories, comments, tags, etc. with any standard feed reader (Bloglines, Google Reader, etc)
    • Java client for remote access via APP
    • Embedded and WAR deployments
    • Web based user interface with Web 2.0 look and feel
  4. WSO2 Business Process Server (BPS) – WSO2 Business Process Server (BPS) is an easy-to-use open source business process server that executes business processes written using the WS-BPEL standard and it’s powered by Apache ODE (Orchestration Director Engine). It provides you the following features,
    • Deploying Business Processes written in compliance with WS-BPEL 2.0 Standard and BPEL4WS 1.1 standard.
    • Managing BPEL packages, processes and process instances.
    • Data Sources support.
    • External Database support for BPEL engine.
    • WS-Security support for business processes.
    • WS-RM support for business processes.
    • Caching support for business processes.
    • Throttling support for business processes.
    • Transport management.
    • Internationalized web based management console.
    • System monitoring.
    • Try-it for business processes.
    • SOAP Message Tracing.
    • Web Services tooling support such as WSDL2Java, Java2WSDL and WSDL Converter.
    • Customizable server – You can customize the BPS to fit into your exact requirements, by removing certain features or by adding new optional features.

All these products are pre-bundled components built on top of WSO2 Carbon framework which is based on the OSGI technology. In fact you can bundle the components to suite your enterprise architecture as all the major features have been developed as pluggable Carbon components.

Web services use SOAP faults to report fault cases back to clients. The faults can be generated from the SOAP framework in a case of invalid SOAP messages, invalid security tokens or they can be generated from the service business logic itself. The fault messages may contain simply a string indicating the error, or it may contain lot of details which could be useful to the clients find the problem. In fact the format of the SOAP fault is a standard. But services can send custom details within the details element in a SOAP fault.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Sender</faultcode>
         <faultstring>..</faultstring>
         <detail> You Custom Message </detail>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

And you can define the schema of your custom fault message in a WSDL, so the clients can prepare to handle fault scenarios. In facts tools like Apache Axis2 WSDL2C, WSDL2Java tool will help you to work with custom faults when they are defined in the WSDL.  Here is an example section of a WSDL with an operation which can throw two faults “MyFirstException”, “MySecondException”.

<!-- fault schemas -->
<types>
 <schema ..>
  <element name="MyFirstException">
   <complexType>
    <sequence>
     <element name="text" type="xsd:string"/>
    </sequence>
   </complexType>
  </element>
  <!-- fault element -->
  <element name="MySecondException">
   <complexType>
    <sequence>
     <element name="number" type="xsd:int"/>
    </sequence>
   </complexType>
  </element>
 </schema>
</types>

<!-- the fault messages -->
<message name="MySecondExceptionFault">
 <part name="fault" element="ns1:MySecondException"/>
</message>

<message name="MyFirstExceptionFault">
 <part name="fault" element="ns1:MyFirstException"/>
</message>

<!-- operation to throw fault -->
<portType name="MyType">
 <operation name="myOperation">
  <input message="tns:myOperationRequest"/>
  <output message="tns:myOperationResponse"/>
  <fault name="MySecondException" message="tns:MySecondExceptionFault"/>
  <fault name="MyFirstException" message="tns:MyFirstExceptionFault"/>
 </operation>
</portType>

Note that the operation “myOperation” is throwing faults “MyFirstException”, “MySecondExcpetion”. If you generate the Java code for this operation, it would be simple as this,

public MyOperationRequest
MyOperation(MyOperationRequest) throws
          MyFirstExcpetion,
          MySecondExcpetion {
  // here is your business logic
}

Anyway we are going to write codes in ‘C’ language, which doesn’t have similar exception mechanism. Let see how we can do it, starting with writing the service and then writing a client.

Writing Services With Custom SOAP Faults

Once you generate the ‘C’ codes for the WSDL using WSDL2C tool, you should first have a look at the skeleton header file.

    /**
     * the generated fault union for operation "myOperation|urn:myuri:1.0",
     * in a case you want to return a fault, put the appropriate adb object for
     * the union variable pointer comes as the last parameter of the method
     */
    typedef union
    {
        adb_MyFirstException_t* MyFirstException;
        adb_MySecondException_t* MySecondException;

    } axis2_skel_MyService_myOperation_fault;

    /**
     * auto generated function declaration
     * for "myOperation|urn:myuri:1.0" operation.
     * @param env environment ( mandatory)
     * @param _myOperation of the adb_myOperation_t*
     *
     * @return adb_myOperationResponse_t*
     */
    adb_myOperationResponse_t* axis2_skel_MyService_myOperation(const axutil_env_t *env,
                                      adb_myOperation_t* _myOperation,
                                      axis2_skel_MyService_myOperation_fault *fault);

And at the very end of the header file, you will see an enumeration of constants corresponding to each fault is generated.

    typedef enum
    {
        AXIS2_SKEL_MYSERVICE_ERROR_NONE = AXIS2_SKEL_MYSERVICE_ERROR_CODES_START,

        AXIS2_SKEL_MYSERVICE_MYOPERATION_FAULT_MYFIRSTEXCEPTION,
        AXIS2_SKEL_MYSERVICE_MYOPERATION_FAULT_MYSECONDEXCEPTION,

        AXIS2_SKEL_MYSERVICE_ERROR_LAST

    } axis2_skel_MyService_error_codes;

That’s all you need to aware of. The plan is whenever you need to report the fault, you have to do three things inside the business logic.

  1. Create the adb object for the fault, in this case either “adb_MyFirstException_t” or “adb_MySecondException_t” and set it to the fault pointer variable.
  2. Set the constant corresponding to the fault using “AXIS2_ERROR_SET” function
  3. return NULL

Here is an example how you do it inside the actual business logic code.

    adb_myOperationResponse_t* axis2_skel_MyService_myOperation(const axutil_env_t *env,
                                      adb_myOperation_t* myOperation,
                                      axis2_skel_MyService_myOperation_fault *fault )
    {
        /* the buisness logic */

        ....

        if(/* checking some condition to throw the "MyFirstException" fault */)
        {
          /* 1. Creating the adb object and set it to the fault pointer variable */
          adb_MyFirstException_t *exp = NULL;
          exp = adb_MyFirstException_create(env);
          adb_MyFirstException_set_text(exp, env, "this is the exception 1"); /* custom value */

          fault->MyFirstException = exp;

          /* 2. Setting the error constant corrosponding to the fault */
          AXIS2_ERROR_SET(env->error,
                      AXIS2_SKEL_MYSERVICE_MYOPERATION_FAULT_MYFIRSTEXCEPTION,
                      AXIS2_FAILURE);

          /* 3. Returning NULL */
          return NULL;
        }

        else if(/* checking some condition to throw the "MySecondException" fault */)
        {
          /* 1. Creating the adb object and set it to the fault pointer variable */
          adb_MySecondException_t *exp = NULL;
          exp = adb_MySecondException_create(env);
          adb_MySecondException_set_number(exp, env, 2);/* custom value */

          fault->MySecondException = exp;

          /* 2. Setting the error constant corrosponding to the fault */
          AXIS2_ERROR_SET(env->error,
                      AXIS2_SKEL_MYSERVICE_MYOPERATION_FAULT_MYSECONDEXCEPTION,
                      AXIS2_FAILURE);
          /* 3. Returning NULL */
          return NULL;
        }

        /* return the response in no fault scenario */
        return response;
    }

That’s all you have to do, Axis2/C will make sure to build the fault and put your custom message inside the details element.

Writing Clients to Handle custom SOAP Faults

After generating the code for clients using WSDL2C tool, this time you should look at the generated stub header file first. It is just similar to the skeleton header files may be except all the “skel” prefixes are renamed to “stub” and additional parameter “stub” for the operation.

    /**
     * the generated fault union for operation "myOperation|urn:myuri:1.0",
     * in a case the server return a fault, the corresponding adb object will be loaded for
     * the union variable pointer comes as the last parameter of the method
     */
    typedef union
    {
        adb_MyFirstException_t* MyFirstException;
        adb_MySecondException_t* MySecondException;

    } axis2_stub_MyService_myOperation_fault;

    /**
     * auto generated function declaration
     * for "myOperation|urn:myuri:1.0" operation.
     * @param env environment ( mandatory)
     * @param _myOperation of the adb_myOperation_t*
     *
     * @return adb_myOperationResponse_t*
     */
    adb_myOperationResponse_t* axis2_stub_MyService_myOperation(axis2_stub_t* stub, const axutil_env_t *env,
                                      adb_myOperation_t* _myOperation,
                                      axis2_stub_MyService_myOperation_fault *fault);

    typedef enum
    {
        AXIS2_STUB_MYSERVICE_ERROR_NONE = AXIS2_STUB_MYSERVICE_ERROR_CODES_START,

        AXIS2_STUB_MYSERVICE_MYOPERATION_FAULT_MYFIRSTEXCEPTION,
        AXIS2_STUB_MYSERVICE_MYOPERATION_FAULT_MYSECONDEXCEPTION,

        AXIS2_STUB_MYSERVICE_ERROR_LAST

    } axis2_stub_MyService_error_codes;

Looking at this, you may have got the idea how to differentiate what fault is being thrown by the server and how to extract the parameters of the custom fault. Here is an example client code correctly handling exceptions.

    /* the structure to keep the fault */
    axis2_stub_MyService_myOperation_fault fault;

    ..... /* the part preparing the request is ignored here */

    /* invoking the "myOperation" operation */
    response = axis2_stub_op_MyService_myOperation(stub, env, op, &fault);

    /* checking the response == NULL implies fault is sent  */
    if(response == NULL)
    {
        /* getting the error number to distinguish the fault */
        error_code = env->error->error_number;

        /* compare error code with constants of each faults */
        if(error_code == AXIS2_STUB_MYSERVICE_MYOPERATION_FAULT_MYFIRSTEXCEPTION) {

            /* extracting out the adb objects */
            axis2_char_t *text = adb_MyFirstException_get_text(fault.MyFirstException, env);

            /* do a printf of the message */
            printf("My First Exception called: with param %s\\n", text);

        }
        else if(error_code == AXIS2_STUB_MYSERVICE_MYOPERATION_FAULT_MYSECONDEXCEPTION) {
            /* extracting out the adb objects */
            int number = adb_MySecondException_get_number(fault.MySecondException, env);

            /* do a printf of the message */
            printf("My Second Exception called: with param %d\\n", number);

        }

    }

Note that this feature is available only in the very latest WSDL2C tool. Try to get latest build from Axis2/Java to use this up to date tool.

You can download the WSDL and codes used in this example from here, https://issues.apache.org/jira/secure/attachment/12399724/case45.zip

January 31st, 2009Making Good SOA Great

WSO2 is preparing for the first major release of their enterprise java product series after adapting the OSGI technology. You can already try out the betas from the wso2.org site.

  1. WSO2 Web Services Application Server (WSAS)
  2. WSO2 Enterprise Service Bus (ESB)
  3. WSO2 Registry
  4. WSO2 Business Process Server (BPS)

With the power of OSGI you will be able to customize these products for your need just by mixing and matching the components within these products. If you like to learn more about this, just have a loot at the following ebook released by WSO2.

Making Good SOA Great

Making Good SOA Great

Once you have a web service, you can write clients to invoke that service from any language, mostly with the help of a framework written in to that particular language. When it comes to C, the most popular choice is Apache Axis2/C framework. When you are using Axis2/C to write web service clients, you need to learn about AXIOM which is a easy to use high performing XML model and the service client API which can be used to actually invoke the service. Lets look at the code.

#include <stdio.h>
#include <axiom.h>
#include <axis2_util.h>
#include <axiom_soap.h>
#include <axis2_client.h>

axiom_node_t *build_om_payload_for_helloworld_svc(
    const axutil_env_t * env);

int
main()
{
    const axutil_env_t *env = NULL;
    const axis2_char_t *address = NULL;
    axis2_endpoint_ref_t *endpoint_ref = NULL;
    axis2_options_t *options = NULL;
    const axis2_char_t *client_home = NULL;
    axis2_svc_client_t *svc_client = NULL;
    axiom_node_t *payload = NULL;
    axiom_node_t *ret_node = NULL;

    /* Set up the environment */
    env = axutil_env_create_all("helloworld.log", AXIS2_LOG_LEVEL_TRACE);

    /* Set end point reference of helloworld service */
    address = "http://localhost:9090/axis2/services/helloworld";

    /* Create EPR with given address */
    endpoint_ref = axis2_endpoint_ref_create(env, address);

    /* Setup options */
    options = axis2_options_create(env);
    axis2_options_set_to(options, env, endpoint_ref);
    axis2_options_set_action(options, env,
                             "http://ws.apache.org/axis2/c/samples/helloworldString");

    /* Set up deploy folder. It is from the deploy folder, the configuration is picked up
     * using the axis2.xml file. You need to set the AXIS2C_HOME variable to the axis2/c
     * installed dir.
     */
    client_home = AXIS2_GETENV("AXIS2C_HOME");
    if (!client_home || !strcmp(client_home, ""))
        client_home = "../..";

    /* Create service client */
    svc_client = axis2_svc_client_create(env, client_home);
    if (!svc_client)
    {
        /* reporting the error */
        printf
            ("Error creating service client, Please check AXIS2C_HOME again\\n");
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        return -1;
    }

    /* Set service client options */
    axis2_svc_client_set_options(svc_client, env, options);

    /* Build the SOAP request message payload using OM API. */
    payload = build_om_payload_for_helloworld_svc(env);

    /* Send request */
    ret_node = axis2_svc_client_send_receive(svc_client, env, payload);

    if (ret_node)
    {
        /* extracting out the content from the response */
        axis2_char_t *om_str = NULL;
        om_str = axiom_node_to_string(ret_node, env);
        if (om_str)
            printf("\\nReceived OM : %s\\n", om_str);
        printf("\\nhelloworld client invoke SUCCESSFUL!\\n");

        AXIS2_FREE(env->allocator, om_str);
        ret_node = NULL;
    }
    else
    {
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
                        "Stub invoke FAILED: Error code:" " %d :: %s",
                        env->error->error_number,
                        AXIS2_ERROR_GET_MESSAGE(env->error));
        printf("helloworld client invoke FAILED!\\n");
    }

    /* freeing the allocated memory */
    if (svc_client)
    {
        axis2_svc_client_free(svc_client, env);
        svc_client = NULL;
    }

    if (env)
    {
        axutil_env_free((axutil_env_t *) env);
        env = NULL;
    }

    return 0;
}

Here is the implementation of the “build_om_payload_for_helloworld_svc” function that build the request SOAP message using Axiom/C. Note that axiom_element and axiom_node has one to one association. We use node to to navigate the XML, where as axiom_element to store the data.

/* build SOAP request message content using OM
           <ns1:greet xmlns:ns1="http://ws.apache.org/axis2/services/helloworld">
                <text>Hello World</text>
           </ns1:greet>
*/
axiom_node_t *
build_om_payload_for_helloworld_svc(
    const axutil_env_t * env)
{
    axiom_node_t *helloworld_om_node = NULL;
    axiom_element_t *helloworld_om_ele = NULL;
    axiom_node_t *text_om_node = NULL;
    axiom_element_t *text_om_ele = NULL;
    axiom_namespace_t *ns1 = NULL;
    axis2_char_t *om_str = NULL;

    ns1 =
       axiom_namespace_create(env, "http://ws.apache.org/axis2/services/helloworld",
                               "ns1");
    helloworld_om_ele =
        axiom_element_create(env, NULL, "greet", ns1, &helloworld_om_node);
    text_om_ele =
        axiom_element_create(env, helloworld_om_node, "text", NULL, &text_om_node);
    axiom_element_set_text(text_om_ele, env, "Hello World!", text_om_node);
    om_str = axiom_node_to_string(helloworld_om_node, env);

    if (om_str)
    {
        printf("\\nSending OM : %s\\n", om_str);
        AXIS2_FREE(env->allocator, om_str);
        om_str = NULL;
    }
    return helloworld_om_node;
}

So lets see how the same thing is done with C++. For C++ we use WSO2 WSF/C++

#include <stdio.h>
#include <WSSOAPClient.h>
#include <OMElement.h>
#include <iostream>
#include <AxisFault.h>
using namespace std;
using namespace wso2wsf;

OMElement build_om_payload_for_helloworld_svc();

int main()
{
    WSSOAPClient * sc = new WSSOAPClient("http://localhost:9090/axis2/services/helloworld");
    sc->initializeClient("helloworld_blocking.log", AXIS2_LOG_LEVEL_TRACE);
    {
        /* generating the payload */
        OMElement * payload = build_om_payload_for_helloworld_svc();

        OMElement * response;
        try
        {
            /* invoking the web service */
            response = sc->request(payload, "http://ws.apache.org/axis2/c/samples/helloworldString");

            /* printing the response */
            if (response)
            {
                cout << endl << "Response: " << response << endl;
            }
        }

        /* handling the fault */
        catch (AxisFault & e)
        {
            if (sc->getLastSOAPFault())
            {
                cout << endl << "Response: " << sc->getLastSOAPFault() << endl;
            }
            else
            {
                cout << endl << "Response: " << e << endl;
            }
        }
        delete payload;
    }
    delete sc;
}

You can see lines of code is reduced a lot. And you can see it from the code to build the request XML as well.

/* building the request soap message
   <ns1:greet xmlns:ns1="http://ws.apache.org/axis2/services/helloworld">
        <text>Hello World</text>
   </ns1:greet>
 */
OMElement build_om_payload_for_helloworld_svc()
{
    OMNamespace * ns = new OMNamespace("http://ws.apache.org/axis2/services/helloworld", "ns1");
    OMElement * payload = new OMElement(NULL,"greet", ns);
    OMElement * child = new OMElement(payload,"text", NULL);
    child->setText("Hello World!");

    return payload;
}

WSF/C++ is build on top of Axis2/C. You can see the WSF/C++ API is designed very carefully to make it easy to use without breaking the flexibility provided in the C API. So C++ developers can straightaway use WSF/C++ to develop their web service consumers. Anyway Axis2/C API still has the power of embedding easily in to scripting languages (Like it is done in WSF/PHP, WSF/Ruby) and probably deploy in legacy systems that doesn’t support C++ compiled binaries. So you have the options to select the most sutiable one for your application.

Now you can view the article I wrote titling “Introduction to PHP Data Services“. There I explain how you can design and implement Data Services in PHP using WSF/PHP Data Services Library.

This article covers,

  1. Designing your Data Service API.
  2. Writing the Data Service.
  3. Deploying and Testing Data Service.
  4. Make the Data Service available in both SOAP and RESTful form.
  5. Use of WS-* features in your Data Service.

If you are thinking of adapting SOA in to your database backed PHP applications, this article will be a good starting point.

PHP is one of the famous choice, when it comes to develop a web site. As the web evolve with the emerge of web service, REST (REpresentational State Transfer) concepts, the PHP language is also adapted to the new requirements specially with the availability of new SOA (Service Oriented Architecture), REST frameworks and libraries. Anyway there were hardly any guides, references or samples that properly describe the methodologies of developing REST applications using PHP.

The book “RESTful PHP Web Services‘ by Samisa Abeysinghe certainly fill this gap. It can be used as a step by step guideline for newbies to learn the concepts and write simple RESTful PHP applications and Mashups. And even experienced developers would find this a great reference to keep nearby while working with RESTful Web Services in PHP. And it has lot of code samples, utility functions that developers can use it in their applications.

RESTful PHP Web Services - Samisa Abeysinghe

About the Author

Samisa Abeysinghe is a well recognized name in the web services world. He lead the development of Apache Axis2/C and WSO2 WSF/PHP, two famous open source web service frameworks for ‘C’ and PHP. In addition to his deep knowledge in the subject, his experience in involving with the community and the enterprise for years and working as a lecturer in universities, should have influenced a lot in writing this book.

The Arrangement and the Content

The arrangement of the book is done really well to make sure the reader can go through it in the right sequence. All the content is bundled just within 200 pages. So you don’t need to allocate a lot of time to go through the whole book. It is organized into 7 chapters and two appendixes which are mostly independent from each other.

The first chapter is completely devoted to explain the concepts of RESTful web services. It basically explains what is RESTful web service and why it is needed. And it briefly mentions about the currently available REST Frameworks for PHP.

The second chapter introduce some PHP codes that do REST web service requests and handles the XML responses using both DOM and SimpleXML APIs. And in the third chapter it shows more code samples specially about consuming real world web services like BBC, Yahoo and an earthquakes information service. Theses codes are written as mashups mostly combining two services to produce more meaningful information.

The forth chapter is about  designing and writing web service providers. Its counterpart, writing web service consumers is described in the chapter five. There it demonstrate a library system that operate using RESTful webservices. You can map this example to any system that you may like to develop to run with RESTful web services. The chapter five of the book is available as a free download, RESTful PHP Web Services – Chapter 5.

The forth and fifth chapters are not using any framework to write the sample codes on consuming and providing web services. But in the sixth chapter it shows the use of Zend framework to do write them. There it rewrites the same example (The RESTful library system) in MVC (Model -View – Controller) approach using the functionalities of Zend framework. (In fact the View in the service is omitted).

The seventh chapter is about debugging web services. Debugging is a much needed step in any software development cycle. So if you are a newbie, you should read this chapter before start writing any of your own code. This introduces tools and methodologies to make your debugging easy and effective.

The book contains two appendixes. They are too really useful as the chapters of the book. In the first appendix it explains another REST web service framework, WSO2 Web Services Framework for PHP (WSF/PHP). To demonstrate it uses, some selected functionalities of the example library system (that is mentioned in chapters 4, 5, 6) is re-implemented using WSF/PHP. And it shows you how you can convert this RESTful system to a SOAP system in a minute. The second appendix provides you a code of a class (RESTClient), that you can use in consuming web services very effectively.

Recommended Readers

This book assume you have some knowledge in PHP. But it doesn’t require you to know anything related to web services, REST or XML. As you read the first few chapters, you will have a good understanding on the concepts and the basic applications of REST and XML using PHP. And the later chapters will guide to get deeper knowledge in writing complex and real world applications.

If you are a professional developer, you can skip the introduction chapters and jump directly to where you need to refer. For an example, if you use this book as a reference in designing and developing RESTful web service providers, you can directly read the chapter4 – Resource Oriented Services, chapter6- Resource Oriented Clients and Services with Zend Framework and probably the chapter 7 – Debugging Web Services.

This book contains the same example system (the library system) written in three different approaches, first without using any framework support, second using the Zend Framework, third using WSF/PHP. Each of them has its own pros and cons. So if you want to determine the approach more suitable to your requirements, or thinking of migrating from one to another, this book will be an ideal resource for you.

As you may have already noticed, this book contains lot of code samples. All the concepts are followed by simple code samples that explain the concept. In appendix it gives you a complete code for RESTClient class that you can use to call any REST service. Apart from the code of the example library system written using different frameworks, it has lot of codes for calling public web service APIs. And the explanation of the code is also done really well.

So it is clear this book is more targetting readers who like to implement PHP RESTful Systems in practice. And it covers enough concepts that you needed to know in writing practicle applications. So this book can take you from the zero knowlege to a deeper knowlege of RESTful PHP Web Services.

Same as web pages, web services also sometime require  client authentication. The most frequent way of authentication is the use of WS-Security Username token which authenticate clients based on the username and passwords. There can be situations where clients need to be authenticated based on its IP or its domain.

If you are writing web services from PHP (Using some PHP web service framework like WSF/PHP), You can use the PHP variables, $_SERVER["REMOTE_ADDR"] and $_SERVER["REMOTE_HOST"] to find the clients ip within the service logic code. If the client’s IP is static you can directly use the $_SERVER["REMOTE_ADDR"] and if it is dynamic you can use the $_SERVER["REMOTE_HOST"] which will be derived by reverse DNS look of the clients IP.

Here is one example of the use of these $_SERVER[] variables inside service logic.

 
function members_only_func($in_message) {

    // getting the clients IP.
    $remote_addr = $_SERVER["REMOTE_ADDR"];

    if($remote_addr == "67.205.26.154" ||
       $remote_addr == "124.43.59.95") {
       // generates the message for authenticated clients.

       return $valid_out_message;
    }

    // otherwise throw an exception
    throw new WSFault("Sender", "Failed to Authenticate");
}

$operations = array("membersOnlyOp" => "members_only_func");

$service = new WSService(array("operations" => $operations));

$service->reply();

“WSO2 carbon is a componentized, customizable SOA Platform, You can adapt the middleware to your enterprise architecture, rather than adapt your architecture to the middleware”.

December 18th, 2008Data Services Best Practices

In simple term, data services are exposing data as web services. Anyway it is not a complete definition. Actually there are situations where we use data services not only to read data, but also to create, update or delete data. So it is better say data services are doing CRUD (Create, Read, Update, Delete) operations for data through web services. Simply it is like providing a web service interface for the database.

Anyway exposing  a database directly as a web service is like violating the first principles of software engineering. It will tightly couple the database structure with the interface, so whenever you do a simple change to the database schema, you will have to change the web service interface which will no doubt break all the clients depending on it.

So first of all, you have to design the service interface independent of the database schema you have. Most of the time you will able to find some query that would map the service interface to the database schema.

For an example think of publishing data in database table (say for table name “Games”) like this.

Teams
GameID Venue Date Team1 Team2 Team1Score Team2Score
1 xxx stadium 2008-12-18 Italy Sweden 34 33
2 yyy stadium 2008-12-19 France Spain 51 50

You will directly able to map these data to data service. So the response payload for a “getGames” operation would be something like,

<getGamesResponse>
   <Game>
      <Venue>
         xxx stadium
      </Venue>
      <Date>
         2008-12-18
      </date>
      <Team1>
          Italy
      </Team1>
      <Team2>
          Sweden
      </Team2>
      <Team1Score>
          34
      </Team1Score>
      <Team2Score>
          33
      </Team2Score>
   </Game>
   <Game>
      <Venue>
         yyy stadium
      </Venue>
      <Date>
         2008-12-19
      </date>
      <Team1>
          France
      </Team1>
      <Team2>
          Spain
      </Team2>
      <Team1Score>
          51
      </Team1Score>
      <Team2Score>
          50
      </Team2Score>
   </Game>
</getGamesResponse>

You can get this done with a SQL query simply as this,

SELECT * FROM `Games`

Say later if you decided to restructure the database table so the new database schema would be like this,

Games
GameId Venue Date
1 xxx stadium 2008-12-18
1 yyy stadium 2008-12-19
GamesTeams
GameId TeamId score
1 1 70
1 2 33
2 1 51
2 3 50
Teams
TeamId Name Coach
1 Italy Mr. ABC
1 Canada Mr. PQR
2 Spain Mr. XYZ

(Note here the Games and Teams are associated in the GamesTeams table.)

You can still use a query like the one in following to provide the same service interface, because it returns the same result set as the earlier one.

   SELECT Games.Venue,
              Games.Date,
              Team1.Name AS Team1,
              Team2.Name AS Team2,
              GameTeam1.Score AS Score1,
              GameTeam2.Score AS Score2
         FROM Teams Team1,
              Teams Team2,
              GamesTeams GameTeam1,
              GamesTeams GameTeam2,
              Games
        WHERE GameTeam1.gameId = Games.gameId  AND
              GameTeam2.gameId = Games.gameId AND
              GameTeam1.teamId = Team1.teamId AND
              GameTeam2.teamId = Team2.teamId AND
              Team1.teamId <> Team2.teamId AND
              Team1.name=?

This allows you to keep the service interface unchanged, regardless of the changes you done to the database schema.

In addition to that, we can uses the features of the data service libraries to give meaningful names for the response elements. If we take above example itself, say you want to rename ‘Score1′ to ‘Team1-Score’ and ‘Score2′ to ‘Team2-Score’. But the dash character (‘-’) cannot be used as a variable in a database query. But you can provide that in the map of sql name to element name when you are writing the data service.

If you are using WSF/PHP php data services Here is how you provide that mapping,

$outputFormat = array("resultElement" => "getGamesResponse",
                      "rowElement" => "game",  // this is the repeating wrapper element for each game
                      "elements" => array( "Venue" => "Venue", // this is the mapping of xml name => sql name
                                           "Date" => "Date",
                                           "Team1" => "Team1",
                                           "Team2" => "Team2",
                                           "Team1-score" => "Score1", // we are using different names for sql and xml
                                           "Team2-score" => "Score2"));

If you write it using Java Data Services, you can use do this with the following configuration xml,

        <result element="getGamesResponse" rowName="game">
            <element name="Venue" column="Venu" />
            <element name="Date" column="Date" />
            <element name="Team1" column="Team1" />
            <element name="Team2" column="Team2" />
            <element name="Team1-Score" column="Score1" />
            <element name="Team2-Score" column="Score2" />
        </result>

Another consideration, when talking about the best practices of designing web services or data services is the granularity of the service interface. We say a web service is fine grained if the service contains tons of small operations. The opposite of that is the coarse grained services, which contains large but few operations. And it is recommended to use the later approach, you can see why from the following example.

Lets say you are developing a web service to upload some information. In order to upload the information first the user have to be authenticated and then the content should be validated. Then only he can submit the actual information. Say you design a fine grained web service for that. So it has three operations.

  1. authenticateUser
  2. validateContent
  3. submitInformation

If you design a coarse grained service interface it will be just the ‘uploadInformation’ operation. And all the three operation defined earlier will be called within the service logic and the clients will not be aware of that.

So here are some disadvantages that I see in the fine grained interface design compared with coarse grained design.

  1. The coupling is too high. Since the client is linked with the service in three adapters. Say you decided to change the service so that you first validate the content and depending on the content it sometime bypasses the authentication. You can’t do this with the former approach (fine grained approach) without changing the clients. But if it were designed as a coarse grained service (just one uploadInformation operation), the client need not to be changed.
  2. Two much time consumed for the transmission. Since we used three web service calls to do a single task the latency of the operation will largely depend on the network latency which will no doubt is comparatively very low. So the performance of the operation is degraded.
  3. The clients can bypass some steps!, Say in your fine grained service, some client bypass the authentication and validateContent steps and jump directly to the sumbitContent operation. In fact you have to write special code to make sure the clients call the service in the correct sequence, otherwise it will be a big security hole.

So I think these three points will be enough to explain why you should try to design a coarse grained interface for your web service.

You can apply these principle when you write data services as well. Lets take the same example explained above. Say there is another table that keep the scoring shots of each game like the one in following.

ScoringShots
GameID Time ScoringTeam ScoringPlayer

Here also you can keep the operation like ‘getGames’ which we defined in the above section. That operation only provide the basic information like the winner and the scores. So if the clients want to know about scoring shots as well, he have to call another operation, say getScoringShots(game) that will return the scoring shots results for a given game. If in practice the clients only need to know about scoring shots of few selected games, then this approach is ok.
But say normally clients need to know about the scoring shots of each and every games. Then they have to call the operation ‘getScoringShots’ multiple times. That’s when the lesson we just learn about the granularity can be applied. We can actually provide another operation, say ‘getGamesDetailed’ that actually bundle the details of scoring shots for all games with other information about the game. Here is snip of the response XML, I’m talking about.

<getGamesDetailedResponse>
   <Game>
      <Venue>
         xxx stadium
      </Venue>
      <Date>
         2008-12-18
      </date>
      <Team1>
          Italy
      </Team1>
      <Team2>
          Sweden
      </Team2>
      <Team1Score>
          34
      </Team1Score>
      <Team2Score>
          33
      </Team2Score>
      <!-- additionally we have ScoringShots element -->
      <ScoringShots>
          <Shot>
              <Time> xxx </Time>
              <ScoringPlayer> xxx </ScoringPlayer>
              <ScoringTeam> xxx </ScoringTeam>
              <Score> xxx </Score>
          </Shot>
          <Shot>
              <Time> yyy </Time>
              <ScoringPlayer> yyy </ScoringPlayer>
              <ScoringTeam> yyy </ScoringTeam>
              <Score> yyy </Score>
          </Shot>
      </ScoringShots>
   </Game>

   <Game>
    <!-- Another game details are mentioned here -->
   </Game>

   <!-- More Games -->
</getGamesDetailedResponse>

You can generate this kind of response using the nested query support of the data services libraries.
You can checkout more details about nested queries in php data services from my old post about php data service API.


© 2007 Dimuthu’s Blog | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress