Showing posts with label WSDL. Show all posts
Showing posts with label WSDL. Show all posts

?xsd option added to WSF/PHP

Friday, December 31, 2010

?xsd is an standard option to serve an xsd file imported within a wsdl. This was a missing feature in WSF/PHP. In WSF/PHP automatic wsdl generation, it does not generate additional xsds which are imported by the wsdl and hence this option would not be required. However, with wsdl mode, you could have additional xsds imported in the wsdl. Now you can obtain these xsds with the option ?xsd=xsdfilename.xsd.

image

ScreenCast - How to Consume a Web Service Using WSF/PHP

Wednesday, October 29, 2008

You can watch a Screencast on How to Consume a Web Service Using WSF/PHP from WSO2 Oxygent Tank (wso2.org) developer portal

WSDL Generation From PHP - Using Different Names in WSDL and PHP Code

Thursday, October 23, 2008

In Generating WSDL from PHP code, you may need to generate schema types with different names to the corresponding PHP classes. This post describes how you can do that.

Coding Schema Inheritance in PHP

Tuesday, October 21, 2008

This post "Coding Schema Inheritance in PHP" describes How inheritance is used in XML Schema and how it is mapped to PHP code from wsdl2php tool in WSF/PHP.

Demo on Providing PHP Web Service with Username Token

Thursday, October 16, 2008

I wrote a blog on Calender DEMO which shows a real world use of the user name token in web service authentication. It describes how you declare different policies per operation in a WSDL and provide authentication information from a callback function.

Developing WSF/PHP Webservices With Contract First Approach - 2 Minutes Introduction

Monday, September 8, 2008

Are you finding a quick guide to develop a web service starting from a WSDL (contract first approach). Have a look at my blog on Developing WSF/PHP Webservices With Contract First Approach - 2 Minutes Introduction

WSF/PHP WSDL Generation 2 Minutes Introduction

Friday, September 5, 2008

If you want a quick look at how to generate a WSDL from a PHP Script Read my blog on WSF/PHP WSDL Generation 2 Minutes Introduction

Howto Build Custom SOAP Headers in WSDL Using Axis2/C and WSF/PHP

Thursday, August 21, 2008

WSF/PHP latest trunk has the support for sending and serving custom headers in the WSDL Mode. Read this blog about Howto Build Custom SOAP Headers in WSDL Using Axis2/C and WSF/PHP for more details about the API and how you would declare custom headers in a WSDL.

XML Attributes in your payload

Friday, June 27, 2008

If you want to have xml attributes in your message payload you have to design a WSDL so that it contains schema types with attributes. For an example

<xs:complexType name=\"myType\">
<xs:sequence>
<xs:element name=\"demo1\" type=\"xs:string\"/>
<xs:element name=\"demo2\" type=\"xs:string\"/>
</xs:sequence>
<xs:attribute name=\"demo3\" type=\"tns:derivedType\"/>
</xs:complexType>



PHP webservices demo site have samples WSDLs that defines attributes http://labs.wso2.org/wsf/php/solutions/wsdl_mode/AttributeService.php?wsdl. And you can test a sample service setting your clients endpoint to http://labs.wso2.org/wsf/php/solutions/wsdl_mode/AttributeService.php. Write your client with the help of the generated code for the WSDL. You can try it online from Here. And make sure you have installed WSF/PHP to do all of these.

Choose among multiple services, multiple ports

Thursday, June 19, 2008

If your wsdl has multiple services and multiple ports, You can tell your PHP client to use a preferred service and port by setting "serviceName" and "portName" option in the WSClient.

For an example if you take wsdl1.1 with multiple services and ports like this,

<wsdl:service name=\"Adder1\">
<wsdl:port name=\"SOAP11port_http\" binding=\"ns0:AdderSOAP11Binding\">

<soap:address location=\"http://localhost:8080/axis2/services/Adder1\"/>
</wsdl:port>
<wsdl:port name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\">

<soap12:address location=\"http://localhost:8080/axis2/services/Adder1\"/>
</wsdl:port>
<wsdl:service/>
<wsdl:service name=\"Adder2\">

<wsdl:port name=\"SOAP11port_http\" binding=\"ns0:AdderSOAP11Binding\">
<soap:address location=\"http://localhost:8080/axis2/services/Adder2\"/>

</wsdl:port>
<wsdl:port name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\">
<soap12:address location=\"http://localhost:8080/axis2/services/Adder2\"/>

</wsdl:port>
<wsdl:service/>


You can select the Adder2 service with SOAP12port_http with the following optional arguments to the getProxy method.

$client = new WSClient(array(\"wsdl\" => \"your_wsdl\"));

$proxy =
$client->getProxy(\"Adder2\", \"SOAP12Port_http\");



This can be represented in wsdl2 as following,

<service name=\"Adder1\" interface=\"ns0:AdderPortType\">
<endpoint name=\"SOAP11port_http\" binding=\"ns0:SOAP11Binding\" address=\"http://localhost:8080/axis2/services/Adder1\"/>

<endpoint name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\" address=\"http://localhost:8080/axis2/services/Adder1\"/>
</service>

<service name=\"Adder2\" interface=\"ns0:AdderPortType\">
<endpoint name=\"SOAP11port_http\" binding=\"ns0:SOAP11Binding\" address=\"http://localhost:8080/axis2/services/Adder2\"/>

<endpoint name=\"SOAP12port_http\" binding=\"ns0:AdderSOAP12Binding\" address=\"http://localhost:8080/axis2/services/Adder2\"/>
</service>

Note that here portName you provided is considered as the endpoint name under the selected service.

When you don't provide either serviceName and the portName, wsf/php will pick the first serviceName and portName listed in the wsdl.

Although multiple services in the same wsdl is very rare, multiple ports /endpoints in the same service is very common. Specially when you support multiple versions of SOAP, addressing, or even completely different policies for the interface you will surely be having multiple ports.

WSF/PHP Code generated for Some famous Web Services

Sunday, June 15, 2008

If you ever wanted writing a client for some famous public web service, WSF/PHP will make your task easy. You want proofs?, Ok, here are some links to famous web services and generated WSF/PHP code to invoke the service.

 




































Service NameWSDLWSF/PHP generated code

Alexa Web Search

http://websearch.amazonaws.com/doc/2006-02-15/AlexaWebSearch.wsdl

http://labs.wso2.org/wsf/php/wsdl2phptool.php?wsdl_url=http%3A%2F%2Fwebsearch.amazonaws.com%2Fdoc%2F2006-02-15%2FAlexaWebSearch.wsdl&generate_type=client

Alexa Top Sites

http://ats.amazonaws.com/doc/2005-11-21/AlexaTopSites.wsdl

http://labs.wso2.org/wsf/php/wsdl2phptool.php?wsdl_url=http%3A%2F%2Fats.amazonaws.com%2Fdoc%2F2005-11-21%2FAlexaTopSites.wsdl&generate_type=client

Amazon EC2 Service

http://s3.amazonaws.com/ec2-downloads/2006-06-26.ec2.wsdl

http://labs.wso2.org/wsf/php/wsdl2phptool.php?wsdl_url=http%3A%2F%2Fs3.amazonaws.com%2Fec2-downloads%2F2006-06-26.ec2.wsdl&generate_type=client

Betfair Service

https://api.betfair.com/global/v3/BFGlobalService.wsdl

http://labs.wso2.org/wsf/php/wsdl2phptool.php?wsdl_url=https%3A%2F%2Fapi.betfair.com%2Fglobal%2Fv3%2FBFGlobalService.wsdl&generate_type=client

"opParams" option for WSService

Tuesday, May 6, 2008

The option "opParams" is an optional parameter to the WSService. If you set opParams to WSMESSAGE the service function would be like this,

/* this is the service function */
function echoFunction($inMessage /* with the type of WSMessage */) {

$outMessage = new WSMessage($inMessage->str);


return $outMessage; /* with the type of WSMessage */
}

$operations = array("echoString" => "echoFunction");


$opParams = array("echoFunction" => "WSMESSAGE");
/* WSMESSAGE is the default value for this situation */

$service = new WSService(array(


"opParams" => $opParams,

"operations" => $operations))

Note that when you provide WSMESSAGE to the "opParams", the service operation parameters(both input and output) are of the type WSMessage.
Now say we put "MIXED" in there like the one in following
/* this is the service function */
function echoFunction($inMessage /* with the type of string */) {

$outMessage = $inMessage;

return $outMessage; /* with the type of String */
}

$operations = array("echoString" => "echoFunction");


$opParams = array("echoFunction" => "MIXED");
/* MIXED is the default value for this situation */

$service = new WSService(array(

"wsdl" => "http://localhost/echostring.wsdl",
"opParams" => $opParams,

"operations" => $operations))

Here note the difference in the service operation. Now the argument types are strings. This types are defined in the wsdl which is provided as an argument to the WSService.

So it is clear

When "wsdl" is provided the opParams are default to "MIXED",
otherwise it is default to "WSMESSAGE".

So you don't need to provide the opParams option explicitly in both above cases.

WSDL Mode Enhancements

Tuesday, February 26, 2008

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.

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..

You still like RPC-Enc style WSDLs

Friday, January 25, 2008

RPC-Encoded is a WSDL style you find in the WSDL 1.1 spec. For some reason in WSDL 2 (fortunately) these style concept of WSDL has been thrown away and only the Document literal style has been survive. So now RPC-Encoded is kind of a deprecated style.

I think there are two main reason that made RPC-Encoded not to use anymore.

First is as first part of its name (RPC stands for Remote Procedure Call) imply this is used to do remote procedure call through network. This lead to appear lot of fine grained services which do just very simple function call through the network. This violates a kind of principal (or just a best practice) of web services, that is you should design a coarse grained fixed interface for a web services. So this was -1 for RPC and +10000 for Document style WSDLs.

Second reason for its failure is the second part of its name, the encoding mechanism. It uses soap encoding which is really tedious to implement, (In fact I am thinking of doing an implementation for Axis2/C, but it seems not that straight forward) And it seems different implementations are hard to inter-operate with this encoding. This made WS-I to prohibit use of RPC-ENC and promote doc-lit.

Anyway we can see still there are many people who ask for RPC-Enc style wsdl support. I think this is because of the legacy systems they are using.

Web Service Framework for PHP
also has great support on DOC-Lit style than RPC-ENC. But still It is a good tools for legacy system developers, since it gives the basic functionalities like dynamic-invocation and wsdl-generation with the RPC-Enoded wsdl s as well.

What is Missing in PHP SOAP Extension?

Wednesday, January 23, 2008

Couple of days back, I blogged about the features of SOAP extension. Now, are these features good enough. Yes they sure are for simple SOAP services.

However, simple SOAP services draws much criticism, specially form REST fans. If you want to do only simple stuff with SOAP, why not use REST? I see that to be a valid argument, especially in the PHP world, given that HTTP is the dominant transport.

In fact, the real value of SOAP comes, when things get complex, more enterprise in nature. That is where the QoS comes into play. SOAP is not that much useful, when you want to use the Fliker upload images, you of course and use the REST API. SOAP is useful when you want to send an invoice, that contains special discounted rates, securely to one of your customers. You have to be absolutely sure that only that customer sees it. And may be you are using a spread sheet or a PDF file to record the invoice and you want to send it as it is. This requires the need to send binary attachment with security with SOAP. And if you are lucky, your customer's system too would use PHP, however, in this heterogeneous world, it may well be that the customer is on .NET or using J2EE.  In short, you need a interoperable comprehensive SOAP stack.

PHP SOAP extension is good to get started, to play around with. However, it falls much short in meeting the enterprise demands in the SOA era.

Can you improve it, to support security and binary attachments? Of course you can. However, the concern is that the time it would take to make it interop side by side with .NET and Java implementations. They have taken years to come to that stage. I have seen how much effort has been spent on Apache Axis2/Java and Apache Axis2/C. Even if you have people with right expertise, WS-Security alone would take at least two person years to complete.

It is the WSDL mode that most users love to use. And if you ever have worked with a WSDL tool, you know how hectic it is to support all the user scenarios. Specially the schema support is an endless game. Most of the interop issues pop up with WSDLs. WSDL mode in SOAP extension already have enough interop issues. And there are no plans to support WSDL 2.0. Let alone, the most critical feature to support in WSDL is the WS-Policy support. Specially when WS-Security in in use, the security policies are the way of conveying rules of the level of security to be used and the rules to follow. Even if basic WS-Security is implemented based on some library like xmlsec, supporting policies would require a WS-Policy processing engine. That too will require at least one person year of work.

In summary, it would be years before serious Web services could be implemented with PHP SOAP extension. Web services are complex!

WSDL Generation with PHP

Thursday, January 10, 2008

WSDL is the key for sharing the service interface. Some people call this the 'contract'. Sometimes, developers have access to an already written WSDL. So they can use that and generate either the client code or the service code or both. This is called the 'contract first model'. Sometimes, what we have is a PHP script, and we want to expose that as a service. In that case, we have the code and we would like to generate the WSDL. This approach is called the 'code first model'.

WSDL generation is supported with WSO2 Web Services Framework for PHP and is done using PHP reflection and an annotation parser. To generate a WSDL from a given PHP Web service, a ?wsdl request should be sent to the server. For example, if you want to generate the WSDL for the service echoService.php, a request should be sent as,

http://localhost/services/echoService.php?wsdl

This will generate a WSDL that adheres to 1.1 specification. You can also generate WSDL 2.0, you can use ?wsdl2 in place of ?wsdl.

For more details, you can refer tot he WSDL generation API documentation.