RIA and Mashups with SOAP and REST

Friday, February 29, 2008

Rich Internet Applications and Mashups are made possible with Web services.

Some prefer SOAP and some REST, and Web services using either technology can be used to realize RIA and Mashups. The demo Web site that we are building with PHP web services would have many hosted online samples of RIA and Mashups. Keep your fingers crossed, WSF/PHP demo site will be available soon. How soon? Well, next week.

Article on PHP and .NET Interoperability

Thursday, February 28, 2008

The latest article on WSF/PHP, titled, WSO2 WSF/PHP Interoperability with Microsoft WCF, explains how you can get PHP Web services to work with Windows Communication Foundation.

It clearly explains the steps on how to write a PHP SOAP client to use a public .NET Web service in WSDL mode.

Schema "anyType" in WSF/PHP

Tuesday, February 26, 2008

Have you seen any schema that contain elements in 'anyType' like this,
       <xsd:schema elementFormDefault="qualified" targetNamespace="http://www.wso2.org/php">
<xsd:element name="echoString">

<xsd:complexType>
<xsd:sequence>
<xsd:element name="inMessage" type="xsd:anyType"/>

</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="echoStringResponse">
<xsd:complexType>

<xsd:sequence>
<xsd:element name="returnVal" type="xsd:anyType"/>
</xsd:sequence>

</xsd:complexType>
</xsd:element>
</xsd:schema>

This type of schemas allow users to set any types at run-time. Now WSF/PHP allows users to use this facility in PHP. For an example,
So if any one want to build the following payload,

<echostring xmlns="http://www.wso2.org/php">
<inmessage>
code and string
</inmessage>
</echostring>

You can just use following array to generate this,
$res = $proxy->echoString(array("inMessage" => "code and string"));

or using the classmap,

class echoString
{
public $inMessage;
}

$echostr = new echoString();

$echostr->inMessage = "test1";

$proxy->echoString($echostr);
Similarly you will be able handle the response..

WSDL Mode Enhancements

WSDL mode in WSF/PHP is getting improved day by day. Dimuthu has done many improvements, including class map support and array support.

I managed to fix some RPC style related issues and also add support for the 'choice' and 'all' constructs. There are some work to be done in WSDL mode to integrate it, but we can generate code for WSDL mode now.

If you want to work with WSDL files in PHP, WSF/PHP would be the most comprehensive toolkit out there.

Attachments Interop with .NET

Sunday, February 24, 2008

I have been working on an article on the WSF/PHP interoperability with .NET. I used the samples form the WSE toolkit for .NET and successfully interoperated with the .NET service using PHP client. The idea was to use the MTOM service form .NET as it is and download a binary attachment using a PHP client. This is because, many users of WSF/PHP query consuming .NET services. I faced no issues in making the PHP client talk to the .NET service.

wsdl2php now Supports Server Side

Friday, February 22, 2008

WSO2 WSF/PHP wsdl2php code now supports server side. I added server side support yesterday.

Now users can write both clients and services in WSDL mode with minimal effort. You just have to generate the code and follow the TODO instructions in the generated code.

This feature will be available with the upcoming 1.2.1 release.

WSF/PHP Plugin for Uniform Server WAMP

Tuesday, February 19, 2008

WSF/PHP is now available as a plugin for the Uniform Server.

Download the WSF/PHP plugin by going to The Uniform Server plugins page. WSF/PHP plugin is listed under the 'User Made Plug-Ins' section. Unzip the plugin and follow the steps in the readme file, and you should have a working WSF/PHP installation with The Uniform Server.

WSF/PHP Solutions Site

We are working on a site to host some working solutions to demo the power of Web services as well as the power of WSF/PHP framework.

The demo site would include a data services demo, a SOA calendar demo, a WS-Security demo and also some .NET interop demos.

wsdl2php for WSF/PHP

Sunday, February 17, 2008

I wrote the initial version of wsdl2php for WSF/PHP WSDL mode over the weekend. You can have a look here: https://svn.wso2.org/repos/wso2/trunk/wsf/php/scripts/wsdl2php.php

The road map for wsdl2php is already being planned.

The next release of WSF/PHP would have this tool. We also plan to host an online version with our proposed WSF/PHP demo site.

5 Important things about WSF/PHP

Friday, February 15, 2008

Open source with Apache licence

WS-* support

Attachments capability

REST Support

Interoperability

 

Read more form Dinesh's blog

How Code Generation Makes Development Easy Over Traditional WSDL Mode

Thursday, February 14, 2008

Yesterday Samisa's blog revealed new approach that WSF/PHP is going to take in the next major release.

WSF/PHP is going to introduce pre code generation for both Web Service clients and services for PHP developers. I think this may little strange to PHP people who used to expect things happening in run time. But sometime it s better to tests different paths to test and pick the ideal method.

I see several advantages in static code generation over current run-time support for the WSDL mode.
1. The usability is high,
Currently we should write classes manually in order build the data tree of the payload, For that you need to have at least some idea of WSDL and XML Schema. But we cannot expect an average user identify these types and write PHP Classes by hand. So it is better we have systems generating classes.

2. Low error-prone
If you have set of classes pre-defined to use in your system it will be no doubt less error-prone than using classes written by yourself. Because current way you may do errors both in writing classes and invoking services, so generated code will eliminate the errors in writing classes.

3. Rapid Development
It would give you some part of code written for you

4. Sample Demos
Easy to generate sample demos for a particular WSDL, so users will be able to follow them in their application

5. Performance,
If we can bypass the wsdl mode with the newer code generation approach that would enhance the performance, So surely in the first step the generated code would be mostly run using the current wsdl mode, so there will be no performance improvement.

6. Easiness in testing
Mostly this open the path to automate testing.

Code Generation for WSDL Mode

Wednesday, February 13, 2008

Both WSF/PHP and SOAP extension has WSDL modes. But none of them has the tools for generating code for a given WSDL. Because of this, the users are in hot water when it comes to implementing the complex type mappings for the request and handling response. If you make a simple mistake in SoapVar or SoapParam classes, debugging could take hours or even days before you get to know the problem.

To address this issue, WSF/PHP is coming up with a nice proposal. Implement code generation tool that can generate all complex type classes along with some demo code. So on one hand, you do not have to write the complex class mappings manually. And on the other hand, you will be provided with some sample code that would help you understand how to consume the service described by WSDL. WSF/PHP already have the model in place to implement the tool. It is only a matter of time before someone put all the pieces together and come up with the code generator.

WSDL Generation with WSF/PHP - Arrays and Complex types

When you are working on code first approach you want to derive the contract WSDL from the code that you already have for the Web Service.

If you may have worked on Java or .NET Web Services you already familiarized with this approach. PHP developers are also provided the opportunity to work on this approach with WSF/PHP. You only need to give a simple introduction for your service operations and their parameter types as annotations, and you will get the WSDL generated in a flash.

Here is how you will put the annotations for a simple operation like add.

<?php

/**
* operation add
* @param int $x operand1 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @param int $y operand2 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @return int $result
*/

function add($x, $y)

{
return array("result" => $x + $y);

}

$operations = array("add" => "add");
$opParams = array("add" => "MIXED");


$svr = new WSService(array("operations" => $operations,
"opParams" => $opParams,
"serviceName" => "Calculator"));


$svr->reply();

?>
Here just examine how the operation parameters are described. If this is not clear you can have a look at the wsdl generation manual[http://wso2.org/project/wsf/php/1.2.0/docs/wsdl_generation_api.html]. It describe the annotation format in a simple fashion.

Anyway in WSF/PHP 1.2.0 you didn't have a way to specify when the input/output parameters are arrays. But in the upcomming 1.2.1 release you will get this facility.

For an example you can add an operation to add vectors like this,

/**
* operation addVectors
* @param array of int $x operand1 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @param array of int $y operand2 <- This is the PHP type
* maps to xs:int <- This is the schema type
* @return array of int $result
* maps to xs:int <- This is the schema type
*/

function addVectors($x, $y)
{

$result = array();
for($i = 0; $i < count($x); $i ++)

{
$result[$i] = $x[$i] + $y[$i];
}

return array("result" => $result);
}
NOTE: you should update the $operations and $opParams with the new operation.

Note the change in annotation notation, you have add a prefix called 'array of' (just 'array' is enough) and you will have the elements maxOccurs="unbounded" in the WSDL means you are having arrays as input and output parameters in your service operation.

How about providing complex types as input and output parameters. That also will available in the WSF/PHP 1.2.1 release.

For an example say you want to add matrices. Here is how your code will look like.


/**
* operation addMatrices
* I have considered matrix as an array of Rows, which in tern array of columns
* @param array of object Row $x operand1 <- This is the PHP type
* maps to non xs:type <- This is required
* @param array of object Row $y operand2 <- This is the PHP type
* maps to non xs:type
* @return array of object Row $result
* maps to non xs:type
*/

function addMetrices($x, $y)
{

$result = array();
for($i = 0; $i < count($x); $i ++)

{
$row1 = $x[$i];
$row2 = $y[$i];
$result[$i] = new Row();
$result[$i]->cols = array();
for($j = 0; $j < count($row1->cols); $j ++)

{
$result[$i]-> cols[$j] = $row1[$j] + $row2[$j];
}

}
return array("result" => $result);
}


/**
* @namespace http://my.org/test/calculator/demo
*/

class Row
{
/**
* @property array of int cols columns
* maps to xs:int
*/

public $cols;
}


NOTE: you should update the $operations and $opParams with the new operation.

Note that you only have to put 'object class_name' to declare that that the parameter is expected to have that PHP class type.

Use WSDL Elements Maps to Your PHP Classes.

Tuesday, February 12, 2008

WSF/PHP allows you to map schema elements and types in your WSDL to PHP Classes in your code.. You can find a good example of this in the samples/wsdl_generation directory in the WSF/PHP pack.

You have to provide the map of wsdl type to the PHP class name as an option to both WSClient(in a case it is a client) and WSService(in a service).

From WSF/PHP 1.2.1 patch release you will not need to provide the full map of classes to schema construct. Since the engine will be intelligent enough to pick the class with the same name as schema construct when the class is not provided in the class map. If there is no class like that at all, the engine will create a unnamed class and allow to access its properties as it was a class like made to represent that schema construct.

So hope you will enjoy the new improvements to the API.

WSF/PHP 1.2.1 on the way

Friday, February 8, 2008

After a month of time, WSF/PHP is preparing for its 1.2.1 patch release. Sanjaya have uploaded the artifacts here for RC1. After doing some heavy tests, the release would be happened early next week.

One of the key feature of this release is improved WSDL mode and WSDL generation support.

In 1.2.0 we had support for simple WSDL generation like this.

<?php

/**
* addUser
* @param string $name here string is for php type
* this maps to xs:string (this is really optional declaration)
* @param int $age the age
* @return int $status
*/

function addUser($name, $age)
{

/* some logic add the user */
return 1;
}

/* map of service operation to php function */
$operations = array("addUser"=> "addUser");


/* this is required in the wsdl generation */
$opParams = array("addUser"=>"MIXED");

$service = new WSService(array("operations"=> $operations,
"opParams"=> $opParams,
"serviceName" => "User"));


$service->reply();

?>


There, the annotations are used to provide meta data about the Service, input and output parameter types.
If you are going to use the new release you would be able to improve the above code to more organized way like one in the following.

<?php

/**
* addUser
* @param object User $user : note the "object User" as the php type.
* @return int $status
*/

function addUser($user)
{
/* some logic add the user */

return 1;
}

/**
* @namespace http://im.me/types the namespace
*/

class User
{
/**
* @property string $name
* schema type xs:string - this is still optional
*/


public $name;
/**
* @property int $name
* xs:int
*/

public $age;
}

$clasmap = array("User"=> "User");

/* map of service operation to php function */

$operations = array("addUser"=> "addUser");

/* this is required in the wsdl generation */
$opParams = array("addUser"=>"MIXED");


$service = new WSService(array("operations"=> $operations,
"opParams"=> $opParams,
"classmap"=> $classmap,

/* the serviceName can provided as an option */

"serviceName" => "User"));

$service->reply();


?>


There we use class "User" to declare a schema type in the WSDL. So if you want to add method like getUsers you can share this type with the current addUser method. Here is how you would define getUsers method with correct annotations. Hopefully you should add this method to "operations" and "opParams" options as well.

/**
* @param string $condition
* @return array of object User $users : note the array of is prefixed
* to the php type
*/

function getUsers($condition)
{
$user1 = new User();
$user1->name = "Hiro";
$user1->age =23;


$user2 = new User();
$user2->name = "Clair";
$user2->age = "14";


return array("users" => array($user1, $user2));

}
This illustrate how you should extract the request and build the response in your logic when there are arrays and class types in your service operations.

Well how you would write a client for this operations. Here is a sample client that use simple arrays to build requests and return response. Similarly if you set "classmap" option to the WSClient you would instead build the requests and extract responses from PHP class objects..


<?php
$client = new WSClient(array("wsdl"=>"http://localhost/mails/06_blog/MuchNewService.php?wsdl"));


$proxy = $client->getProxy();

//add user operation
$res = $proxy->addUser(array("user"=>

array("name" => "cyler", "age" => 28)));

print_r($res);

//getUsers operation
$res = $proxy->getUsers(array("conditions" => "none"));

print_r($res);
?>

Hope you all will enjoy this new set of features..

Custom Faults in WSF/PHP

Monday, February 4, 2008

Custom faults is very much required in cases you have to report exception from your business logic. It is equal to throwing and catching exception in Java, or PHP5 except that one who throws the exception is in one side and the one who catches would be in somewhere else in a network.

WSF/PHP has bound this custom faults in to a PHP language constructs, so PHP developers will not need to worry about web service messages and their formats. Here is a simple example of how you can throw and catch custom faults.

your server side will be

function greet($name)
{
if(is_my_enemy($name)) {

throw new WSFault("sender", "you are not my friend");
return "<xml>{$name}</xml>";

}

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

$service->reply();


You will handle the fault in the client side with this code,

$client = new WSClient(array("to" => "http://localhost/url/to/above/service.php"));
try{

$res = $client->request($req);
}
catch(Exception $e)

{
if($e instanceof WSFault) {
just_report_error($e->reason);
}

}

Get Real with REST

Sunday, February 3, 2008

WSF/PHP is the only PHP SOAP API out there that enable you to write a single service script and expose that using both as REST and SOAP with a single deployment.

There was this criticism, however, that the level of REST support was not that RESTful. There is good news now. Apache Axis2/C, the heart of WSF/PHP, has improved the REST support to make it more RESTful. WSF/PHP would soon integrate this improved REST features.

The good news is that not only there would be more support for HTTP methods like PUT and DELETE, it would also provide means to map different PHP functions to a custom resource URI. Keep your fingers crossed.

Meanings of common SOAP faults and Error Messages in WSF/PHP

Friday, February 1, 2008

If you have work with web services for some time, you should be familiar with different SOAP faults. There are mainly two kind of SOAP Faults that you encounter in web services.

1. SOAP faults originated from the web service engine. - On which I will be talking today..
2. SOAP faults originated from the service business logic. (Custom faults)

In WSF/PHP, you will find separate PHP class represent soap faults called WSFault. It has two mandatory fields, one is 'code' which most commonly has the value "sender", and the other is 'reason'. Here the reason will give you a good understanding of the problem mostly in your request message.

You can always echo the fault reason using a try, catch block. (Taken from WSF/PHP echo sample)
i.e.

try {
$res = $wsclient->request($req);
}
catch (Exception $e) {

if ($e instanceof WSFault) {
printf("Soap Fault: %s\n", $e->Reason);
}

else {
printf("Message = %s\n",$e->getMessage());
}

}


Sometime the reason itself doesn't descriptive, this is mostly because of the same reason can be caused by different faults in the message and soap engine just cannot determine which one is the most close one.

In addition to soap faults, the WSF/PHP tells you some other problem in your request by throwing PHP native exceptions. You can see a description of the error through getMessage method in the Exception class. Please note how we are catching the both form of exception in the try catch block.

Here is a little list of messages you may get from above listed code and what their actual meanings,

1. Message = request payload should not be null

This is not a SOAP fault, just an error occurred by the soap engine. This can be caused by
i. As it says the $req in the above code is NULL.
ii. $req contains malformed XML.
i.e. something like
$req = "<hello></hello>"; /* note that '>' is missing in first hello */

2. Message = Error , NO Response Received

This too is not a SOAP fault, but very common message. Here is some of the possible reasons that can cause this message.

i. As it means, the Server is not sending anything to the client in reply. This it self can be due to several reasons like
*. The server is not on.
*. The server have crashed while processing the request. :(
*. The server takes long time. So the timeout value expires..
ii. Next server send something in reply, but it is not a soap message. That is you have most probably send a soap request to a non-soap server.

iii. The service endpoint is invalid if the endpoint is WSF/PHP service. In normally case this should return a soap fault saying service not found. but since WSF/PHP consider a script running on the PHP as a service, and PHP doesn't always invoke WSF/PHP code unless it has use WSF/PHP objects, this just return a 401 Not found. Surely this is not a soap message. so the client will be displayed the error 'No Response Received'

3. Soap Fault: Operation Not Found

The SOAP engine fails to identify the service operation. Here I assume the soap service also written in WSF/PHP

i. if soap action or wsa addressing is not used, (that is "action" option in WSClient or WSMessage constructor),
Name of the first Element of the request ( That becomes the operation name), is not matched with the expected operation of the service which can be specified in the "operation" array of the WSService object.
E.g. (The correct code)
If request message is
<request>
content
</request>

the service should be created with
$service = new WSService("operation" => array("request" =>"requestHandlerFunction"));

if these two entities has different values, this soap fault will be sent.

ii. if the action (either the soap action or wsa action) is specified,
the client side and the server side have different value for action + the early point satisfied.
E.g. (The Correct code)

$client = new WSClient(array("to" => "http://myhost/samples/request_service.php",
"action" => "myrequest"));
And the server side
$service = new WSService("operation" => array("request" =>"requestHandlerFunction"), //the operation to function map
"actions" => array("myrequest" => "request")); //here is the action to operation map

Note that if these action are different but the service operation name is same as the request node name, still the operation will be successfully dispatched.

These are the common messages that I have met with. In addition to that if you have used security features, you may have seen WSFault reasons relating to security which are mostly self-descriptive.

Please comment here, if you met with any other regular error, fault messages.

Comparing Hello World

I posted Hello World Services and Hello World Clients with PHP SOAP extension, NuSOAP and WSF/PHP.

NuSOAP looks the most clean, with its natural mapping for PHP types to service request/response serialization. Native SOAP extension again can deal with PHP types, but there are problems when it comes to customizing element names the way we wish.

WSF/PHP code looks more bulky, because of the XML in-out model. However it has the advantage of being able to control the payload the way we wish.

The key point is that, as far as the API is concerned, the three alternatives are not that much apart. They look almost the same. For a service, you define a function and declare that function to be an operation of the service. For a client, you provide the service endpoint and send the request with the required parameters.

One thing to note with SOAP extension and NuSOAP is that you have to register the operations one by one. For small services this is fine. But if you have 5, 10 operations, this would mean multiple calls. With WSF/PHP, you can provide an array of operations.

Anyway, the bottom line is, all three are usable simple for the simple cases.

I would like to visit WS-Addressing with PHP in the near future and see how these Web services framework would support that spec.