Sending And Handling Faults From PHP Web Service
Thursday, October 30, 2008
ScreenCast - How to Consume a Web Service Using WSF/PHP
Wednesday, October 29, 2008
WSF/PHP Services Performance test with WSDL Caching
Tuesday, October 28, 2008
Introduction to Reliable Messaging with WSF/PHP
Monday, October 27, 2008
With WSF/PHP you can add reliability to your web services integrations . Due to the nature of PHP, WSF/PHP supports only single channel reliable messaging. Single channel means you are using the same channel to transmit both the request and response.
When reliable messaging is used, in addition to the actual message being transmitted , there will be handshake interactions between the client and the service to make sure that the sent message is actually delivered to the service. In addition the , reliable messaging middleware make sure that if the receiver endpoint down, it will keep polling till the message is delivered etc.
Let see how you can implement a simple reliable messaging client using WSF/PHP.
These are the requirements.
1. You service endpoint should be able to handle single channel reliable messaging.
2.Then you need to enable addressing.
In RM, the communication happens using a sequence. The initial handshake is to build this sequence, and with a sequence , one or more application messages is transmitted. Once the messaging transmission is complete, the sequence is terminated.
So the messages exchanged in a single channel scenario is as follows. I am using the actual xml messages exchanged in the echo_client_rm.php sample that comes with WSF/PHP release here.
1. Client sending the CreateSequence Message to the service.
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>http://localhost/samples/reliable/echo_service_rm.php</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:6dbfe9a0-304f-415e-91d1-49d2993bcf56</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<wsrm:CreateSequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:AcksTo xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsrm:AcksTo>
<wsrm:Offer xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>df2ceab0-b04f-428a-bb94-0cfdcb0a524b</wsrm:Identifier>
</wsrm:Offer>
</wsrm:CreateSequence>
</soapenv:Body></soapenv:Envelope>
2. Service responding with a CreateSequenceResponse message.
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>http://www.w3.org/2005/08/addressing/anonymous</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse</wsa:Action>
<wsa:From>
<wsa:Address>http://localhost/samples/reliable/echo_service_rm.php</wsa:Address>
</wsa:From>
<wsa:MessageID>urn:uuid:48020317-4e90-4b79-97ae-2fa9b78c544b</wsa:MessageID>
<wsa:RelatesTo wsa:RelationshipType="http://www.w3.org/2005/08/addressing/reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">urn:uuid:6dbfe9a0-304f-415e-91d1-49d2993bcf56</wsa:RelatesTo>
</soapenv:Header>
<soapenv:Body>
<wsrm:CreateSequenceResponse xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>8883a8b9-9f6a-4e40-b78a-872a2708a4b3</wsrm:Identifier>
<wsrm:Accept xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:AcksTo xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsa:Address xmlns:wsa="http://www.w3.org/2005/08/addressing">http://localhost/samples/reliable/echo_service_rm.php</wsa:Address>
</wsrm:AcksTo>
</wsrm:Accept>
</wsrm:CreateSequenceResponse>
</soapenv:Body></soapenv:Envelope>
3. Client sending the sequence Message
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsrm:Sequence soapenv:mustUnderstand="1" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<wsrm:Identifier>8883a8b9-9f6a-4e40-b78a-872a2708a4b3</wsrm:Identifier>
<wsrm:MessageNumber xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">1</wsrm:MessageNumber>
<wsrm:LastMessage xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
</wsrm:Sequence>
<wsa:To>http://localhost/samples/reliable/echo_service_rm.php</wsa:To>
<wsa:Action>http://wso2.org/wsfphp/samples/echoString</wsa:Action>
<wsa:MessageID>urn:uuid:8e275ba1-b34b-49c1-92fa-ce86782ff803</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<ns1:echoString xmlns:ns1="http://wso2.org/wsfphp/samples">
<text>Hello World!</text>
</ns1:echoString>
</soapenv:Body></soapenv:Envelope>
4. Service Responding with a SequenceAcknowledgement message. Since this is an echo service, in addition to sending the acknowledgement, the service also initiate a sequence here and send the application message back to the client.
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsrm:Sequence soapenv:mustUnderstand="1" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<wsrm:Identifier>df2ceab0-b04f-428a-bb94-0cfdcb0a524b</wsrm:Identifier>
<wsrm:MessageNumber xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">1</wsrm:MessageNumber>
<wsrm:LastMessage xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
</wsrm:Sequence>
<wsrm:SequenceAcknowledgement soapenv:mustUnderstand="0" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<wsrm:Identifier>8883a8b9-9f6a-4e40-b78a-872a2708a4b3</wsrm:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="1"/>
</wsrm:SequenceAcknowledgement>
<wsa:Action>http://wso2.org/wsfphp/samples/echoString</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>http://localhost/samples/reliable/echo_service_rm.php</wsa:Address>
</wsa:ReplyTo>
<wsa:From>
<wsa:Address>http://localhost/samples/reliable/echo_service_rm.php</wsa:Address>
</wsa:From>
<wsa:MessageID>urn:uuid:307e881d-8ac7-4cb4-8acf-0eb04831707f</wsa:MessageID>
<wsa:RelatesTo wsa:RelationshipType="http://www.w3.org/2005/08/addressing/reply" xmlns:wsa="http://www.w3.org/2005/08/addressing">urn:uuid:8e275ba1-b34b-49c1-92fa-ce86782ff803</wsa:RelatesTo>
</soapenv:Header>
<soapenv:Body>
<ns1:echoString xmlns:ns1="http://wso2.org/wsfphp/samples">
<text>Hello World!</text>
</ns1:echoString>
</soapenv:Body></soapenv:Envelope>
5. Client send the SequenceAcknowledgement message to the service.
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsrm:SequenceAcknowledgement soapenv:mustUnderstand="0" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<wsrm:Identifier>df2ceab0-b04f-428a-bb94-0cfdcb0a524b</wsrm:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="1"/>
</wsrm:SequenceAcknowledgement>
<wsa:To>http://localhost/samples/reliable/echo_service_rm.php</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/SequenceAcknowledgement</wsa:Action>
<wsa:MessageID>urn:uuid:3b2b7a50-f962-4027-b240-5eea57142df1</wsa:MessageID>
</soapenv:Header>
<soapenv:Body/></soapenv:Envelope>
6. Now the service sends back a TerminateSequence Message.
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence</wsa:Action>
<wsa:MessageID>urn:uuid:6e8178c6-a566-4010-a77e-d05af67ad21a</wsa:MessageID>
</soapenv:Header>
<soapenv:Body>
<wsrm:TerminateSequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>df2ceab0-b04f-428a-bb94-0cfdcb0a524b</wsrm:Identifier>
</wsrm:TerminateSequence>
</soapenv:Body></soapenv:Envelope>
Similarly the client and service exchanges TermianteSequenceResponse messages as well.
I am sure, now you have some understanding on what actually happens when you try to send a soap message reliably from one endpoint to another. In my next blog post, we will discuss how to configure WSF/PHP to implement reliable clients and services.
WSF/PHP WSDL Mode - Handling XML Schema Arrays
Saturday, October 25, 2008
How to learn the SOAP version by looking at a soap message
Thursday, October 23, 2008
I have seen number of questions on the forums on issues related to this. So here are some tips on getting to know spec versions by looking at a soap message with http headers.
Here is an example SOAP1.1 one message.
POST /samples/echo_service.php HTTP/1.1
User-Agent: Axis2C/1.5.0
SOAPAction: ""
Content-Length: 242
Content-Type: text/xml;charset=UTF-8
Host: 127.0.0.1:8080<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ns1:echoString xmlns:ns1="http://wso2.org/wsfphp/samples">
<text>Hello World!</text>
</ns1:echoString>
</soapenv:Body></soapenv:Envelope>
I have marked highlighted the important points.
In SOAP1.1
1. Content-Type will be "text/xml".
2. SOAPAction is a separate HTTP Header
3. SOAP envelope namespace uri is "http://schemas.xmlsoap.org/soap/envelope/"
Here is a SOAP 1.2 message.
POST /samples/echo_service.php HTTP/1.1
User-Agent: Axis2C/1.5.0
Content-Length: 240
Content-Type: application/soap+xml;charset=UTF-8;action="urn:echoString"
Host: 127.0.0.1:8080<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header/>
<soapenv:Body>
<ns1:echoString xmlns:ns1="http://wso2.org/wsfphp/samples">
<text>Hello World!</text>
</ns1:echoString>
</soapenv:Body></soapenv:Envelope>
In SOAP 1.2
1. Content-Type header is "application/soap+xml"
2. SOAP envelope namespace uri is "http://www.w3.org/2003/05/soap-envelope".
3. soap action header will go in the Content-type header as 'action'
Depending on you requirement, you can switch between between soap versions by passing the option "useSOAP"=>1.1 or "useSOAP"=>1.2.
For a service in WSF/PHP, the soap version does not matter since the framework is capable of handling either type.
WSDL Generation From PHP - Using Different Names in WSDL and PHP Code
How to Get WS-Security working without WS-Addressing in WSF/PHP
Tuesday, October 21, 2008
Usually, most security scenarios use WS-Addressing. But there are scenarios that uses security without WS-Addressing. Due to configuration file settings, WSF/PHP works with WS-Security only when WS-Addressing is also used. However, by doing some simple changes to a couple of Xml files, you can get WSF/PHP to support some security scenario's that does not use WS-Addressing.
Here is what you need to do.
1. Step One.
Open the axis2.xml file found in was_c directory. In it, change in inflow by adding another phase named Security as follows.
<phaseOrder type="inflow"> - <!-- System pre defined phases -->
<phase name="Transport" />
<phase name="PreDispatch" />
<phase name="Dispatch" />
<phase name="PostDispatch" />
<!-- End system pre defined phases -->
<!-- After PostDispatch phase, module or service author can add any phase as required -->
<!-- User defined phases could be added here -->
<phase name="Security" />
<phase name="Rahas" />
<phase name="RMPhase" />
</phaseOrder>
I have highlighted the line added in red.
2. Step two
Open the module.xml file found in wsf_c/modules/rampart/ directory and change the inflow elements phase name attribute from "PreDispatch" to "Security" as follows.
<inflow>
<handler name="RampartInHandler" class="mod_rampart">
<order phase="Security"/>
</handler>
</inflow>
Again, I have highlighted the change.
That's all you need to do to get WS-Security to work without using WS-Addressing.
Note that,for this to work, you will have to have either SOAPAction or an element that matches the operation name in Soap Body. Of course there are some WS-Security scenarios that cannot work without WS-Addressing.
Tips on avoiding common WSF/PHP installation issues.
Here are some useful tips avoid common fit falls in installing WSF/PHP.
1. Often users complain that When the run the sample clients, they see the response
"ERROR, WS Client not Found'.
This is often due not setting the wsf.home entry correctly. Make sure to set wsf.home directory to point to wsf_c directory if your are on windows or using pecl installation with WSF/C library installed separately.
Another reason for this is not adding the wsf_c/lib directory to PATH environment variable if you are on a windows system.
2. WSDL Generation and WSDL mode does not work.
This is often due to you not having added the scripts folder found inside the wsfphp distribution to the php.ini's include path entry.
3. Compile WSF/PHP using source gives errors.
This could be due to two issues.
1. First you need to have installed the dev-libraries of PHP, Libxml2 and OpenSSL.
2. Incorrect configure options provided to the configure script.
Often you do not need to provide any options to the configure script since it is written to work as
./configure, make , make install sequence.
RESTful PHP Web Services - Book
My book on RESTful PHP Web Services is now available for download from Packt Publishing.
What you will learn from this book
- Basic concepts of REST architecture
- Consuming public REST-style services from your PHP applications
- Consuming RESTful web services, such as those from leading APIs such as Flickr, and Yahoo Web Search
- Making your own PHP applications accessible to other applications through a RESTful API
- REST support in the popular Zend framework
- Debugging RESTful services and clients
- A case study of designing a RESTful PHP service from the ground up, and designing clients to consume the service
It is also note worthy that there is a dedicated appendix chapter in this book on using WSO2 WSF/PHP.
Coding Schema Inheritance in PHP
How to install WSF/PHP in Debian/Ubuntuu Systems from scratch
Monday, October 20, 2008
How to use Attachment Caching with WSF/PHP
WSF/PHP 2.0.0 has the support for caching attachments ( writing to a file ). This effectively reduces the amount of memory used when sending and receiving attachments and its specially useful, if your application requires to send or receiving a very large file in the scale of megabytes.
WSF/PHP adds two php.ini entries in order to allow attachment caching.
1. wsf.attachment_cache_dir
2.wsf.enable_attachment_caching
wsf.attachment_cache dir is the location where the received attachments will be saved.
wsf.enable_attachment_caching option enables attachment caching.
By default, attachment caching can be done only for attachments larger than 1 MB.
Lets see a code sample on how to use this. This is a simple php service, which reads a binary file and send it to the client as an MTOM attachment.
<?php
ini_set("wsf.enable_attachment_caching", 1);
ini_set("wsf.attachment_cache_dir","E:\\");
function sendAttachment($msg)
{
$responsePayloadString = <<<XML
<ns1:download xmlns:ns1="http://php.axis2.org/samples/mtom">
<ns1:fileName>test.jpg</ns1:fileName>
<ns1:image xmlmime:contentType="image/jpeg" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:myid1"></xop:Include>
</ns1:image>
</ns1:download>
XML;
$responseMessage = new WSMessage($responsePayloadString,
array( "attachments" => array("myid1" => "../resources/large_image.jpg")));
return $responseMessage;
}
$operations = array("download" => "sendAttachment");
$service = new WSService(array("operations" => $operations, "useMTOM" => TRUE));
$service->reply();
?>
Now in above code, I have highlighted the important code pieces.
1. The php ini settings at the top of the code where the attachment_cache_dir is set and attachment caching is enabled.
ini_set("wsf.enable_attachment_caching", 1);
ini_set("wsf.attachment_cache_dir","E:\\");
2. Setting of a fake content id to which the actual attachment is assigned.
href="cid:myid1"
3. Instead of setting binary attachment as an string in the attachment array, we should set the actual path to the file.
array("myid1" => "../resources/large_image.jpg")
Thats all you need to do to get attachment caching working. The same technique can be used for the client as well. It will be consuming lot less amount of memory.
Demo on Consuming Flickr, Yahoo and Amazon Search Web Services
Sunday, October 19, 2008
DEMO on a SOAP and REST Client with PHP
Friday, October 17, 2008
Using Open SSL to manage Your Keys
When it comes to WS-Security, for most of the operations, you will need to have either a certificate, or a key or both. Or you will need to provide a key store. WSF/PHP uses Open SSL library underneath to build WS-Security. Therefore knowing how to work with Open SSL can be really useful.
Lets go through some of the important commands you need to know to effectively get work done using Open SSL.
1. Generating a Certificate using Open SSL.
When generating a certificate, you have to decide whether you want an encrypted key or not. If you select the encrypted key option, your key will be protected by a passphrase. This adds more security to your key since it will be difficult for some one stealing your key to use it. How ever you will need to provide this passphrase, every time you use the key. A self signed certificate is used to sign other certificates.
Use the command
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem
These options tells openssl to generate key length 1024 bits which is valid for 365 days and put both private key and certificate to a file named mycert.pem.
Now you will be prompt to answer a number of questions and then OpenSSL will generate you a self signed certificate. Now if you open the mycert.pem you will see both the private key and the certificate stored there. If you remove the -nodes option, you will be asked to provide a passphrase.
2. Generating a private key and a matching public key using RSA algorithm.
It is sometimes necessary to generate the private key and public keys separately.
You can generate an RSA public key using the option genrsa.
openssl genrsa -out mykey.pem 2048
This generates a rsa private key with 2048 bits.
Using rsa option, you can get the corresponding public key.
openssl rsa -in mykey.pem -pubout
3. Creating a PKCS12 Keystore and adding keys to it.
openssl pkcs12 -export -out mycert.pfx -in mycert.pem -name "My Keystore"
This command generates a PKCS12 key store by exporting the above generated certificate. Here you will be asked for a passphrase as well.
XML Signature
Thursday, October 16, 2008
XML signature is used in WS-Security to sign SOAP messages. Here is a blog post describing XML Signature.
Installing WSF / PHP with Wampserver Article in French
Demo on Providing PHP Web Service with Username Token
Fetching song lyrics
How to build PHP from source
Wednesday, October 15, 2008
It is an interesting thing to build PHP source on a Windows Platform. It is extremely useful to build PHP source with various options specially if you wish to write a PHP extension. Here are some interesting tips on how you can build PHP source on a windows platform.
First you need to download the following dependencies.
1. You need to have visual studio or windows platform SDK install on you machine in order to have the required compiler and build tools.
2. You need to download the PHP build dependencies.
These include
1. Binary tools - Essential
2. Libxml2 - Optional
3. Iconv Optional
4. Zlib - Optional
5. Apache or other web server that you intend to build modules.
6. PHP Source - Essential
7. bindlib-cvs-vc8 - Essential
Most of these tools can be downloaded from here.
Once you have downloaded these tools, you are ready to build PHP from source.
First unzip all these tools to a directory.
Next, open visual studio command prompt and add binary-tools\bin directory to the path.
Now, go to the PHP source extract directory and type,
buildconf.bat
Then run
cscript /nologo configure.js --help
You will see a large number of options as shown above.
Next open the config.nice.bat file located in the php source directory and add necessary configure options for your build
Here are my configuration options
cscript /nologo configure.js "--with-extra-includes=E:\phpbuild\bindlib-cvs-vc8\include;E:\Apache22\include;E:\phpbuild\iconv-1.9.2.win32\include;E:\phpbuild\libxml2-2.6.30.win32\include;E:\phpbuild\zlib-1.2.3.win32\include"
"--with-extra-libs=E:\phpbuild\iconv-1.9.2.win32\lib;E:\phpbuild\libxml2-2.6.30.win32\lib;E:\phpbuild\zlib-1.2.3.win32\lib;E:\Apache22\lib;E:\phpbuild\bindlib-cvs-vc8\lib"
"--enable-debug" "--enable-apache2-2handler" %*
Here I am using the option --with-extra-includes to specify the include paths of the dependency libraries. Similarly --with-extra-libs is used to specify the library path.
I use the options --enable-debug to make it a debug build.
Now run config.nice.bat file.
Next you can try nmake on the command line and it will build the PHP Source.
Bridging the Gap Between Enterprise and Web Applications
WSF/PHP allows web applications to integrate with enterprise applications using the Web Services. Here is a blog post talks about Bridging the Gap Between Enterprise and Web Applications using WSF/PHP.