September 30th, 2008XPath in SimpleXML

SimpleXML as it name imply, is a very simple API to traverse XML implemented specially in PHP language. It is very similar to the XPath, but since it has more PHP friendly syntax PHP developers really like to use it.
As an Example for this XML:

<dwml>
  <data>
    <location>
      <location-key>point1</location-key>
      	<point latitude="37.39" longitude="-122.07"></point>
      </location>
  </data>
  .....
</dwml>

XPATH Query to take the latitude in more general way

/dwml/data/location/point/@latitude

Where as with simple XML it is just a familiar PHP statement,

$simplexml->data->location->point->attributes()->latitude

Anyway still you can use the xpath inside your simplexml code. You can execute xpath queries by calling xpath function from any SimpleXMLEelment. It will return an array of SimpleXMLElement that match your query. So for the above example your XPath query would be something  like this,

$simplexml= new SimpleXMLElement($xml);
$lats =  $simplexml->xpath('/dwml/data/location/point/@latitude');
echo $lats[0];

This simplicity allows you to choose between these two methods interchangeably as best fit per your application. Here are some cases that I think use of XPath is more easy.

Ability to use of XPath shorthand
Take the above example XML it self. If there is only one attribute named ‘latitude’ throughout the XML you can call that value by

//@latitude

If XML node name or attribute name contains characters like ‘-’ which are not allowed in PHP for variable names
In the example if you want to access the value inside ‘location-key’ node using simplexml it would be like,

echo $simplexml->data->location->location-key;

This will not give you the expected result as PHP will try to think ‘location’ and ‘key’ as two taken in ‘location-key’. So this particular code can be replaced with the xpath function.

$keys =  $simplexml->xpath('/dwml/data/location/location-key');
echo $keys[0];

You want to iterate through node with a same name in an XML

If the nodes which we want to iterate is in organized positions in an XML (like the one in following) both approaches can be used with same easiness.

<root>
  <mynode>value1</mynode>
  <mynode>value2</mynode>
  <mynode>value3</mynode>
  <mynode>value4</mynode>
  <mynode>value5</mynode>
</root>

But how if the ‘mynode’ was in different locations in an XML like this,

<root>
  <anothernode>
     <mynode>value1</mynode>
  </anothernode>
  <anotheranothernode>
     <anotheranotheranothernode>
       <mynode>value2</mynode>
     </anotheranotheranothernode>
     <mynode>value3</mynode>
  </anotheranothernode>
  <mynode>value4</mynode>
</root>

You can iterate all the ‘mynode’ nodes with the following xpath query.

//mynode

Note that this case can be handled easily in DOM with the getElementsByName.

To use the power of XPath functions and Axes
You can use the XPath functions like last(), position() and even string manipulation functions like substring() in a XPath statement.
For an example in the above example, if you want only take the value of last ‘mynode’ just use this expression

//mynode[last()]

And you can use the power of axes in Xpath Queries. If you want to iterate all the ancestors from current node just use this query

'ancestor::*'

Access elements with different namespaces

<saleItems>
   <ns1:car xmlns:ns1="http:/toyota.xxx.com">$3000</ns1:car>
   <ns2:car xmlns:ns2="http:/suziki.rrr.com">$4000</ns2:car>
</saleItems>

You want to extract the cars from simpleXML. You can do this by following code.

$simplexml= new SimpleXMLElement($xml);
$ns1_childs = $simplexml->children("http:/toyota.xxx.com");
echo $ns1_childs->car;

$ns2_childs = $simplexml->children("http:/suziki.rrr.com");
echo $ns2_childs->car;

Every time you access a different namespace you have to call the children method with the namespace as an argument.

If you use XPath approach, you first register the namespces with an prefix and just use those prefix in your XPath queries.

$simplexml= new SimpleXMLElement($xml);

$simplexml->registerXPathNamespace("p1", "http:/toyota.xxx.com");
$simplexml->registerXPathNamespace("p2", "http:/suziki.rrr.com");

$toyota_cars = $simplexml->xpath('//p1:car');
$suziki_cars = $simplexml->xpath('//p2:car');

echo $toyota_cars[0];
echo $suziki_cars[0];

SimpleXML is simple and powerful in its native form. But whenever it is impossible or difficult to use you don’t need to go back for tedious DOM or manual string manipulation. You can use the xpath queries to get the work done within the simplexml environment itself.

The REST API for Twitter is very simple to learn and implement. And it has a comprehensive documentation.

Here is some selected operations to just to show its design. Note that here userid should be replaced with a valid twitter user id or user name and the format should be changed to the required output format (.xml, json, rss, atom are possible output formats)

Operation HTTP Verb URL Example HTTP Request (Setting username as ‘dimuthu’ and the output format as .xml)
Get public (all users) statuses GET http://twitter.com/statuses/public_timeline GET http://twitter.com/statuses/public_timeline
Get a user statuses GET http://twitter.com/statuses/user_timeline/userid.format GET http://twitter.com/statuses/user_timeline/dimuthu.xml
Get a particular status GET http://twitter.com/statuses/show/statusid.format GET http://twitter.com/statuses/show/938135815.xml
Create a new status POST http://twitter.com/statuses/update.format POST http://twitter.com/statuses/update.xml
Authorization: Basic xxxx
………..
<status>my status message</status>
Delete a particular status DELETE/ POST http://twitter.com/statuses/destroy/statusid.xml DELETE http://twitter.com/statuses/destroy/939390294.xml
Authorization: Basic xxxx
………..

After having look at this API, the first question I had was whether this API is actually RESTful. In RESTful design we expect to map a resource to a URL and do CRUD (Create, Read, Update and Delete) operations using request with different Http Verbs (POST, GET, PUT, DELETE) with that same URL. Look at my blog on RESTful CRUD Data Services Demo for more clarification.

So if ever the API is designed following the above theory it would have been like this.

Operation HTTP Request
Get all statuses GET http://twitter.com/statuses.xml
Get a particular user statuses GET http://twitter.com/users/{user_id}/statuses.xml
Get a particular statuses of a user GET http://twitter.com/users/{user_id}/statuses/{status_id}.xml
Crete a particular statuses of a user POST http://twitter.com/users/{user_id}/statuses.xml
Update a particular statuses of a user PUT http://twitter.com/users/{user_id}/statuses/{status_id}.xml
Delete a particular statuses of a user DELETE http://twitter.com/users/{user_id}/statuses/{status_id}.xml

So I think although Twitter API is really nice and easy, it is not really a RESTful API. If it was really RESTful, URLs might have been more organized so more easier to remember or predict. But still this API allows thousands of third party application to talk to the twitter, demonstrating the value of  providing web services over just providing some web pages in a website.

PHP Web Services Demo Site contains a set of nice tools that help development of web services in PHP.

  • WSDL2PHP tool – This allow you to generate PHP code for your WSDL. Note that this need your wsdl to be in a URL that it can access.
  • PHP2WSDL tool – Here you can paste your annotated PHP code and get the WSDL (both version 1.1 and 2.0) generated.  You can find the annotation syntax in here.
  • DBS2PHP tool – WSO2 has Data Services library implemented in both Java and PHP. In Java Data Services you give the configuration via an XML (in .dbs extension). Whereas in PHP you give the configuration via a simple PHP code which use arrays to feed the configuration parameters. If you are more familiar in writing XML than PHP, you can first write the XML and then convert it to PHP using DBS2PHP tool.

September 27th, 2008RESTful CRUD Data Services Demo

When you are developing Web Service for CRUD (Create, Read, Update, Delete) operations you may find it is easy to implement it as RESTful service. In this Demo on RESTful CRUD Service You can have an idea how you develop such a service with WSO2 WSF/PHP.

Here we take a scenario of submitting applications (say for a school).

In RESTful world we map a resource to a unique URL. In this demo, application is a resource. We use the URL “application/{id}” to represent a particular application with the id {id}.

You can  use  HTTP verb + Resource URL touples to manipulate the resource with CRUD operations.  Here is how it is done in this particular demonstration.

Request format (HTTP Verb + URL) Operation Semantic
POST applications/{id} Create an application
GET applications/{id} Get an application
PUT applications/{id} Change an application
DELETE applications/{id} Delete an application

Go for the wsf/php demo sitefor the live demo of this service. Visit the demo service source code to see how easy to implement it with WSF/PHP Data Services library.

I wrote a similar blog on Data Services last week to demonstrate how you design the mapping of url to different resources in a RESTful Service.

September 25th, 2008WSF/PHP Webinar

WSO2 WSF/PHP Webinar slides are now online. It basically contains an introduction to the WSF/PHP project, the features in its last week hot release and its enterprise applications.

You can watch the video of the Webinar from here. Visit the WSF/PHP Webinar Page for more details.

Yesterday’s blog on “Using Username token in Authentication” I explained a standard way of authenting SOAP messages in Application layer (Message level Authentication). Anyway you can authenticate SOAP messages in transport level itself. For an example with HTTP Transport we can use the HTTP Basic Authentication for this purpose.

Setting up a client with Authentication Information

With WSF/PHP you can give the username, password and the authentication type as options for WSClient constructor.

	$client = new WSClient(array ("to" => "http://server/myendpoint",
		"httpAuthUsername" => "user",
		"httpAuthPassword" => "user_password",
		"httpAuthType" => "basic"));

Setting up the Server to Handle the Authentication

Since the Http authentication is handled by the transport level, you have to configure your authentication information in your web server itself. (e.g. Apache or IIS).

If you are using Apache, please use this guide to configure your allowed list to access the server.

Username token is a simple token sent inside SOAP message header element with username and password information.  It is used to authenticate SOAP messages in a standardized way.

Sending Username Token

To send username token with WSF/PHP you can use the generic API designed to implement WS-Security scenarios.

  • First you need to declare the security policy saying you are using username token. You can do this either with a policy which is complaint with WS-Security Policy standards or using an associative array. Here we use the second approach which is more PHP-Friendly.
    array("useUsernameToken" => TRUE)
  • With a WSSecurityToken instance we are giving our user parameters. In this case it is username, password and the password type.
    $security_token = new WSSecurityToken(array("user" => "my_username",
                                                    "password" => "my_password",
                                                    "passwordType" => "Digest"));
  • And create the WSClient object with policy and the security token object you just created + with “useWSA” on.  This is to enable the addressing headers in the request message which guide the server to identify the service and the operation.

Here is the complete code for the client.

    // Set up security options
    $security_options = array("useUsernameToken" => TRUE );
    $policy = new WSPolicy(array("security" => $security_options));
    $security_token = new WSSecurityToken(array("user" => "my_username",
                                                "password" => "my_password",
                                                "passwordType" => "Digest"));

    // Create client with options
    $client = new WSClient(array("useWSA" => TRUE,
                                 "policy" => $policy,
                                 "securityToken" => $security_token));

    // Send request and capture response
    $resMessage = $client->request($reqMessage);

Handling Username Token at Server Side
The same options (“policy” and “securityToken”) you gave to WSClient, can be given to WSService object as well. But hard coding values for “username” and “password” in SecurityToken is not much useful at the server side. Because it authenticate only one user. So in order to maintain multiple accounts, you have to have a callback function in php.

// callback function
function my_passwd_callback_function($username)
{
    // logic to return the password for the username
    return $password
}

// setting it to the security token
$sec_token = new WSSecurityToken(array("passwordCallback" => "my_passwd_callback_function",
                                       "passwordType" => "Digest"));

Here in the function you return the password for the username from a database and that information will be used to authenticate the request message.

In PHP you have several ways of sending binary data. It can be primarily categorized in to non-optimized method (send as base64 binary) and optimized method (send as MTOM or SWA). Here I m talking about how to send binaries in above mentioned methods starting from a WSDL.

WSDL

Think you have a WSDL with the following XML Schema.

            <!-- Here is my submitPerson method->

            <xs:element name="submitPerson">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="name" type="xs:string"/>
                        <xs:element name="age" type="xs:int"/>
                        <xs:element name="photo" type="xs:base64Binary"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>

The submit Person method submit the name,age and a photo which is a type of base64Binary.

Generated Class

After generating php class for this piece of code using wsdl2php you will have  the following class.

class submitPerson {

    /**
     * @var string
     */
    public $name;

    /**
     * @var int
     */
    public $age;

    // You need to set only one from the following two vars

    /**
     * @var Plain Binary
     */
    public $photo;

    /**
     * @var base64Binary
     */
    public $photo_encoded;

}

So it is very easy to fill the class with your own data. Note that you only need to fill one of the ‘photo’ or ‘photo_encoded’ fields. If you have binary already converted to base64 then you can use the ‘photo_encoded’ field where as if you only have the row binary just use the ‘photo’ field. Here are my values for this particular example.

$person = new submitPerson();
$person->name = "xxxx yyy";
$person->age = 35;
$person->photo = file_get_contents("/photo/xxxyyy");

Sending Binary as MTOM

Here is the code you need to send the above structure as a MTOM message.

$client = new WSClient(array("useMTOM" => TRUE)); // anyway useMTOM is default to TRUE for WSClient
$proxy = $client->getProxy();

$response = $proxy->submitPerson($person);

Sending Binary as Base64 Encoded string

You only need to change one option. That is setting “useMTOM” to FALSE will send the binary as Base64.

$client = new WSClient(array("useMTOM" => FALSE));
$proxy = $client->getProxy();

$response = $proxy->submitPerson($person);

SWA (SOAP With Attachments)
You can send the binary data as SWA by setting the “useMTOM” option to “SWA”. SWA is also a binary optimized method of sending attachments, but unlike with MTOM you can’t integrate security or reliability with this approach.

September 21st, 2008WSDL2PHP 2 Minutes Introduction

WSDL2PHP makes the development of web service providers and consumers quick and easy. I wrote a 2 minutes guide on developing web services providers sometimes ago. So lets concentrate on developing web service consumers here.

Where is WSDL2PHP?

WSDL2PHP script is included in the WSF/PHP packs. You can find the wsdl2php.php script inside the ‘scripts’ directory of any source or binary package. Or you can use the online wsd2php tool hosted in WSF/PHP web services DEMO Site.

How to Run the Script?

Here is the command

/scripts/wsdl2php.php mywsdl.wsdl > myclient.php

The Code is Generated. How Can I add My Code There?

It is simple. Just search for the comment “//TODO”.
Check for an example here.

You have to write custom code for 2 occasions per operation.

  1. To Provide Input Parameters
  2. To Handle output parameters.

An Example?

Here is the code snippet corresponding to the simpleAdd request for our demo WSDL.

    $input = new simpleAdd();
    //TODO: fill in the class fields of $input to match your business logic

    // call the operation
    $response = $proxy->simpleAdd($input);
    //TODO: Implement business logic to consume $response, which is of type simpleAddResponse

Here is how after I filled my logic in place of TODO comments.

    $input = new simpleAdd();
    //DONE: fill in the class fields of $input to match your business logic

    //-------my code----
    $input->param0 = 2;
    $input->param1 = 3;
    //------------------

    // call the operation
    $response = $proxy->simpleAdd($input);
    //DONE: Implement business logic to consume $response, which is of type simpleAddResponse

    //--------my code-----
    echo $response->return;
    //--------------------

September 20th, 2008SOA Way of Writing PHP

Traditional way of Writing PHP
Let me draw a component diagram of a typical traditional(conventional) PHP web application.MVC Architecture Model

With this design you get the advantages of the client-server architecture and the MVC design pattern.

Advantages of the Traditional Approach

  • You can connect to the server from anywhere that has the connectivity to the centralized server. Say you process purchase orders in your application. Sails agents, customers around the world can connect to the application from their computers and do purchase orders. (Because of the Client-Server Architecture)client-server architecture
  • Doing Changes to the inside of the components (Model, View and Controller) are relatively easy , because of the separation of the logics. But if changes affect to inter-communication of each component then it become harder because of the low granularity. (check disadvantages)

Are their any disadvantages of this approach?
Yes. There are plenty of them. Actually it is lot more than the advantages list.

Disadvantages of the Traditional Approach

  • More Server load: The only server is responsible for maintenance of all the components. And there is no straight forward way to distribute these components in a network.
  • No Interoperability: Can I replace the PHP Presentation layer with a .NET, C, Java Desktop Application with this design? No. PHP components (Model, View, Controller) are communicated in PHP code level through php function calls or may be through PHP object interactions, If you want to integrate .NET/Java to replace one component, you have to change all these function calls, object passings with each components.
    non-interoperability
  • Fine Grained Interfaces: Even when I want to replace some component with another PHP implementation, it is still very difficult to integrate to the running system because of the fine-grained interfaces (Lot of small operations) used in the inter-component communication.
    Mostly this issue comes when integrating new business component to existing business logic within the controller logic. The below is just a figure to demonstrate what is meant by fine-grained interface.
    fine-grained-services
    This causes the application to be slow (more message exchange => more time on the wire =&t; lesser speed), more traffic to the server and most importantly very hard to make interfaces consistent. (There can be many additions and removals of small operations over the time). Check this for learn more about the granularity.
  • Business Process Automation (BPA) is impossible: Your partner companies can not purchase your products through their systems. Because they are only given a browser interface, which need human interaction. You should provide some remote interface to allow their computers to talk to your systems.
    bpa-impossibility
    For BPA, interoperability is really important. Because your partner company may run on completely different platform and use completely different languages. I already proved traditional design will not suit to situation where interoperability is need.
  • Lack of security: With the above approach you have to depend on the transport level security, which is handled by your OS. There can be applications (malicious codes) run top of your OS which have back doors to these information. So for business critical messages you need to have message level security (application to application security) which secure the messages by application itself .
  • Lack of reliability: In any case if the connection is lost, will my messages completely lost?. Here too you depend on the transport level reliability which you don’t have much control of.

So now lets turn to our main topic.

SOA Way of Writing PHP

SOA Model

With SOA, you application is no longer presenting the ‘View’ component directly. Instead it provides your business operations as a Web Service. You may implement a View with PHP using this web service. This approach allows you to implement View not only in PHP but also in other languages like .NET, Java or C as web application or desktop applications.

The business logic access the Data Layer through a Data Service. Simmilarly It can use third party Data services, Web Services to extract out the Data needed in the business process.

Let’s see how it helps you to solve the problems arouse in the traditional approach.

  • Less Server load: The SOA components are natively distributed. You don’t need to process the View and the Data in the same server you process the Buisness Logic.
  • High Interoperability: SOA communication happens through Web Services which is a standard protocol. There are implementations for web services in many languages and for many platforms. You can replace any components with any implementation you prefer. For an example you may first write your business logic in PHP, And as the server load goes high, you can write the buisness module in native language (‘C’) and easily intergreate to the system, without being bother of changing other components.
  • Coarse grained Interfaces: The latest web services standards (e.g. WSDL 2.0) enforce the use of documents for messaging rather than invoking remote procedures. This causes the system to be consistent, maintainable and more responsive.
  • Business Process Automation: Web service provide a platform to machine to machine communication. With the availability of interoperability two companies who use different implementations can communicate easily
  • Security: With a WS-Security implementation you can get message level security in your application. For PHP developers there were no implementation or library that can provide  WS-Security sometime ago. But as WSF/PHP is launched with many implementations for WS-* stack, that gap was closed.
  • Reliability: With the WS-Reliable Messaging you can make sure a reliable communication at the application layer. You can use WSF/PHP to do reliable messaging in PHP

As your business get more complicated you can divide the logic too in to several service components as you do with data and view components. This allows you to extend your application very easily. Here is a rough design of an enterprise SOA application that you may have seen in Java and .NET paradigms. And it is time to see more of these in PHP space as well.

SOA design


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