Wednesday, December 31, 2008

RESTful PHP Web Services

In the last couple of days, I finished reading the book "RESTful PHP Web Services" by Samisa Abeysinghe. It is a book that  focuses on explaining the REST architectural style and its application to PHP. It is written with a very nice flow, starting with the basic principles, and gradually developing samples based on the REST principles and towards the end,explains the construction of a real world REST application. So by reading this book , the reader is able  understand, grasp and go on to build real world distributed REST applications. It requires only the knowledge of PHP language from the reader.

1847195520

In addition to explaining the  REST architectural style with interesting examples and applications, the book also explores the REST frameworks that are available, which can be used to implement your applications, instead of writing your own code from scratch. There are two whole chapters dedicated to explore the building of REST Client and Services using Zend Framework  and WSO2 WSF-PHP Framework.

Author

Samisa Abeysinghe has been involved in open source for many many years and has been a main contributor to many highly successful Open Source  Web Services middleware projects like AxisC++, Axis2/C at apache software foundation. In addition, he has been  leading the WSO2 Web Services Framework effort with products like WSF/C, WSF/PHP, WSF/Ruby. Having got years of experience in building distributed middleware, he has put his knowledge and know how in to this book in a very elegant way.

Content of the Book

The book chapters are organized in such a way that, a user with some PHP language knowledge can go through the book and get all the knowledge he needs to build quality applications incorporating REST principles. The First chapter introduces the  concepts and the tools used to build REST applications.  After explaining the principles and concepts, it also explores existing real world REST applications, how best is to utilize these services to enhance your existing applications and then goes on building real client and services. One great aspect about this book is that it comes with a very nice set of samples with all necessary parts nicely explained. The book also covers, rarely explained know how on debugging REST applications. Throughout the book , the best practices involved in building applications are also highlighted.

I would highly recommend this book to anyone expecting to master the techniques of building RESTful applications in PHP. Reading the book will enlighten you not only on building RESTful PHP applications, but also in the broad area of building reusable distributed applications.

Friday, December 26, 2008

Merry Christmas and Happy New Year

Wish everybody a merry Christmas and a happy New Year !!!!!

Saturday, December 20, 2008

REST Vs SOAP

Both REST ( Representational states transfer) and SOAP is widely adopted techniques for building distributed systems. REST is an architectural style for implementing systems on top of HTTP infrastructure.  A large number of Specifications has been developed on top of SOAP and there are large number of SOAP stacks both open source and proprietary out there implementing large part of this WS* stack.

Both these d techniques have their advantages and drawbacks. Here are few of the advantages and disadvantages of each paradigm.

REST

Advantages

1. Based on few simple principles which are already in wide adoption on the Web itself

2. Can be implemented very quickly.

3. Ideal for providing simple API's to the users. (Eq Whether Services, Flicker, Yahoo REST services )

4. Amount of learning required to get started is minimum in comparison to SOAP

5. Has a very large following amount the scripting community

Disadvantages

1. If the system is a very large one, then designing based on REST could become a very complex task.

2. Implementing Security on a REST system is one major issues. Although HTTPS, and HTTP Authentication can be used,  they only provide transport level security.

SOAP

Advantages

1. Well designed mature technology

2. Has been widely adopted in industry

3. Large number of SOAP stacks available to choose from.

4. Has support for Both Transport level and message level security which is a big advantage over REST.

5. Supports multiple protocol bindings ( Not just HTTP)

6. Ideal for implementing complex enterprise  systems since the SOAP Stacks cater for security, reliability, transactions ect.

Disadvantages

1. Complex in comparison to REST

2. Big learning curve required

3. Difficult to debug a complex system

One great thing about using WSF/PHP is that it can support Both of these techniques simultaneously. However, if you are building a complex system which require  security, I would always recommend the use of SOAP.

Saturday, December 13, 2008

WSO2 Carbon Beta Released

WSO2 Carbon is the new Componetized SOA platform from WSO2. Build on OSGi technology, it enables seamless addition of SOA components to an enterprise deployment of SOA infrastructure, as the need arises.

You can checkout the release notes here.

WSAS - http://tinyurl.com/6nmgue
ESB - http://tinyurl.com/6gxuwr
BPS - http://tinyurl.com/6jtjjj
Registry - http://tinyurl.com/5vd6j5

Friday, December 12, 2008

Getting Started With Axis2/Java

Last week, I was involved with some work in Axis2.  I had to set up Axis2. So I decided to write down the steps incase someone who is going to build axis2 from source and setup a development environment to make some modification to axis2.

Step1. Install maven2

You need to  install Apache Maven 2. Axis2 and many other dependent projects of Axis2 uses maven2 as the build system. Download mavan2 from Apache maven  site.

I used the zip archive of maven. Once you have download, just extract the zip archive a preferred location. For example, my maven2 directory is E:\javasoftware\apache-maven-2.0.9.

image

When extracted, you will find an xml file named settings.xml in the conf directory. You can edit this file and set configurations according to your preferences. One of the important settings in this file is the maven repository location. Maven repository is a directory when, maven downloads and keeps dependency jar files for building a project. Also the mvn install command will copy the built jar file to this repository at the end of a build process as well.  So I configured the repository to location

E:\java\respository.

<localRepository>E:\javasoftware\repository</localRepository>

There are other details like configuring a proxy. You can find a detailed guide here. 

Create an environment variable MAVEN_HOME and set the maven directory as its value.

image

Now add the bin directory to your PATH environment variable.  You can directly add the maven bin directory to path and it will work without the MAVEN_HOME. However, it is always preferable to use an separate  environment variable for ease in conformability.

 image

Now you have configured maven. Open a new command prompt and type mvn -v to verify whether maven is installed properly.Congratulations, you have successfully configured maven on your system.

Step2. Checkout Axis2 and  build using maven2.

You need to have an svn client installed on your machine in order to checkout source code from the svn server. Assuming that you have an svn client.

Checkout Apache Axis2 from https://svn.apache.org/repos/asf/webservices/axis2/trunk/java

checkout

It will take a few minutes to complete the checkout since, axis2 has large amount of source files.  Once you have taken the checkout, open a command prompt, go to axis2 checkout directory, and type mvn clean install to build the axis2 snapshot.

image

It will take some time to download the dependency jars, compile source and run the tests. Since you are building it for the first time, It is better to run the tests as well. In case you want to skip the Unit tests which will consume time, use the option -Dmaven.test.skip

Once the build is completed, the resulting axis2-SNAPSHOT.jar file will be copied to the folder "org\apache\axis2\axis2\SNAPSHOT" within your maven repository.

Use command mvn -e -X install -Dmaven.test.skip=true -Drelease   to build the distribution. This will include

axis2-SNAPSHOT-war.zip
axis2-SNAPSHOT-src.zip
axis2-SNAPSHOT-bin.zip

You can find some useful maven targets for axis2 here.

Step3. Build the project file for IDEA\Eclipse and configure the project

Use the command mvn idea:idea to build the IntelliJ IDEA project file for axis2. Once this command complete's you will find the axis2.jpr project file in the outer most directory.

image

If you prefer using eclipse editor, use mvn eclipse:eclipse to build the eclipse project files.

image

Now double click on the axis2.jpr and open axis2 project in idea IDE. I will go through the steps in configuring the project in IDEA and how to debug ect in my next blog post.

Saturday, December 6, 2008

Apache OFBiz Development ( A beginner's tutorial)

Apache Open For Business (OFBiz) is an open source enterprise automation software project.By open source enterprise automation it mean ERP, CRM E-Business/E-Commerce , SCM , Open Source MRP and so on.

Apache OFBiz Development ( A beginner's tutorial ) is a book from Packt Publishing . It is written by two experienced java developers Jonathan Wong and Rupert Howell. It explains the OFBiz functionality, covers from installing OFBiz to fixing an issue in the actual code :).

What you will learn this book.

  • Learn what OFBiz is, and what it is capable of doing for business.
  • Install and configure OFBiz to optimize system performance.
  • Develop a bespoke OFBiz component. Enhance and modify existing components.
  • Save time by learning how to re-use existing OFBiz code.
  • Explore Entities – the basic units of the framework's Model – to simplify database operations and perform complicated queries.
  • Define, create, and call Java services in the Service Engine to build synchronous and asynchronous communications.
  • Learn syntax and schema for the OFBiz language: MiniLang. Use MiniLang to speed up your OFBiz development.  
  • Acquire valuable development and performance tips that will make your custom applications supreme.

If you are into developing or evaluation open source enterprise automation software at apache, this is a must have book.Here is a sample chapter from the book.

Thursday, December 4, 2008

Using command line to debug your Web Service

You can actually run your PHP Web Service on the command line. One may wonder what the use of doing that ?

The main use case is that, you can test your service, without having to write a client. It is specially useful, if your are following the code first approach.  You can find the code for actually doing this in one of the WSF/PHP samples. It is in fact the simplest sample of all. The echo_service.php.

Lets have a look at how this becomes possible.

 WSService->reply() function takes an optional string argument . 

1. You can pass the actual XML string expected from the client to the reply function. Then, the service can be executed on the command line to see the actual executed output from an operation.

However, this would work only in cases where you using SOAP Body dispatching or WS-Addressing.

In SOAP Body dispatching case, the XML qualified name of the child element of soap body is used to identify the operation which should be invoked.

In case of WS-Addressing, the addressing action header is used.

2. Lets look at a code sample on implementing this.  This is the echo_service.php sample that comes with WSF/PHP

<?php

$requestPayloadString = <<<XML
<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>
XML;

function echoFunction($inMessage) {

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

    return $outMessage;
}

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

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

?>

I have highlighted the important code segments. Note how the Expected soap envelope string is passed to the reply() function as an argument.

3. Now you can execute this service on the command line and get the result.

php echo_service.php

Now you should see the expected output soap envelope after invoking the echoString operation.

4. You can also generate the WSDL for the service on the command line as well. Simply set the reply function argument string to "wsdl" or "wsdl2".

$service->reply("wsdl");

5. Now you can re execute the service and get the wsdl for the service on the command line.

php echo_service.php

This is a very useful feature for debugging your hand coded services  :).

Wednesday, December 3, 2008

Resource Oriented Architecture + PHP

SOA (Service Oriented Architecture ) has been a buzz word for quite some time now and there are large number of frameworks and stacks to support implementing SOA with SOAP being the widely adopted protocol for the implementation of SOA. Similarly ROA( Resource Oriented Architecture talks about a set of guidelines of implementation of a REST architecture. REST architectures can be easily implemented in PHP and has wide popularity among the PHP community since it is based on HTTP and its principles. You can get a good idea about the rest principles by reading this article from infoq.

    As you would have found out from the article above,   Just like SOA talks about services, REST talks about resources.  When using resources, it is important to get the right URL design, then map the correct http methods to the resource. In this sample book chapter from Samisa's  "RESTful PHP Web Services" book, the design of a resource oriented system , and how to implement php clients to access such a rest system is thoroughly  explained. And of course , there is a lot of code samples.

If you are building a REST system, this book is a must have book. It gives you large number of examples and explains the theory and best practices for REST systems. You can get this book from packtpub.com.   

Useful links.

1. REST article

2. Sample Book Chapter

3. Restful Web Services book

Sunday, November 16, 2008

How to contribute to WSF/PHP project

As an open source software development project, WSF/PHP always encourage users,developers to raise bugs, and post patches etc. Of course if you have any great idea related to WSF/PHP or some enhancement to WSF/PHP, you are most welcome to contribute.

Lets see how you can contribute to WSF/PHP project in various ways. If you encounter a bug, you can first check on the svn to see whether it is already fixed as well.

1. How do I provide a patch to WSF/PHP .

Step1.

WSF/PHP uses svn as its version control system. You can checkout the source code of WSF/PHP from the following URL.

https://wso2.org/repos/wso2/trunk/wsf/php/

On windows you can use Tortoise SVN to checkout the source code as follows.

Step 1.

Create a folder to which you will checkout the source code.

Step2. Check out the code

img1

img2 

Now you can make any changes or additions, you would like to make.

Step 3.

Use create patch option in Tortoise svn to create a patch.

image 

This should provide you with a patch file.

Step 4.

Go to WSO2 Jira project and select WSF/PHP project

jira1

Select WSF/PHP project    

 jira2                                         

Go to create new issue options and select WSO2 WSF/PHP from projects drop down menu. Then select the issue type

jira3

Now in this issue form, you can fill out information about the issue.

jira4

Next fill out the issue description, your testing environment, and attach the patch.

jira5

Now click create button to create the issue.

This way you can contribute to WSF/PHP project which is used by a large number of PHP Developers worldwide. Looking forward to your contributions.

Monday, November 10, 2008

Introduction to reliable messaging part 3

In this blog post, we will look at how you can send multiple application messages within a single sequence reliably using

WSClient API.  For this purpose WSClient has an option named willContinueSequence. If you intend to send only a since application message within your reliable sequence, then you do not need to touch this option. However, when sending multiple application messages, you need to use it as follows.

1. When sending the first message, set willContinueSequence=TRUE in WSClient.

2. Send your application messages by using WSMessage object.

3. When you want to send the final application message to be sent within the reliable sequence, set the option lastMessage to true.

Here is a code example demonstrating this.

Step 1. First create an application message.

$requestPayloadString = <<<XML
    <ns1:pingString xmlns:ns1="http://wso2.org/wsfphp/samples/reliable">
        <text>Hello World!</text>
    </ns1:pingString>
XML;

Step 2. Create a WSClient object with willContinueSequence option set to TRUE

$client = new WSClient(array( "reliable" => TRUE, "useWSA" => TRUE, "willContinueSequence" => TRUE));

Step 3. Create and Send WSMessage objects containing application messages.

$message = new WSMessage($requestPayloadString,
           array( "to" => "http://localhost/samples/reliable/ping_service_rm.php",
                  "action" => http://wso2.org/wsfphp/samples/pingString));

$client->send($message);

$message1 = new WSMessage($requestPayloadString,
            array( "to" => "http://localhost/samples/reliable/ping_service_rm.php",
                   "action" => "http://wso2.org/wsfphp/samples/pingString"));

    $client->send($message1);

Step 4. When you want to send the last application message, set the option lastMessage to true in WSMessage object.

$message2 = new WSMessage($requestPayloadString,
    array( "to" => "http://localhost/samples/reliable/ping_service_rm.php",
           "action" => "http://wso2.org/wsfphp/samples/pingString",
           "lastMessage" => TRUE));

$client->send($message2);

Note that this is a ping service and hence the use of the method send in WSClient. You can similarly use request method as well.

Monday, November 3, 2008

Introduction to reliable messaging part 2

In my previous blog post, we had a look at a set of messages exchanged between a web services client and a server using WS-Reliable Messaging protocol.  Today, we will explore the API available in WSF/PHP to achieve reliable messaging.

WS-Reliable messaging API in WSF/PHP is a simple an uncomplicated one. Lets go thorough each of the options available on WS-Client to achieve reliable messaging.

To enable WS-Reliable Messaging you need to use the "reliable" option in WS-Client. However, for WS-RM to work, it is mandatory to have WS-Addressing enabled. There for you need to  enable WS-Addressing or at least define the "action" option in WS-Client. If the action is present, and "reliable" options is set to "true", WSF/PHP will automatically enables WS-Addressing and enables Reliable Messaging. So following options are valid on WS-Client to enable reliable messaging.

1.

oparray["action"] = "http://wso2.org/wso2-wsf-php";

oparray["reliable"]= TRUE;

client = new WSClient(oparray);

2.

oparray["action"] ="http://wso2.org/wso2-wsf-php"

oparray["reliable"]=1.1

In this option, we are telling WS-Client to use WS-RM version 1.1.

In my next blog post, we will explore other configuration options of WSClient and WS-Service

Monday, October 27, 2008

Introduction to Reliable Messaging with WSF/PHP

 

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.

Introduction to Reliable Messaging with WSF/PHP

 

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.

So what is the nature of a reliable messing interaction ?

When reliable messaging is used, in addition to the actually message being transmitted , there will be handshake interactions between the client and the service to make sure that the send message is actually delivered to the service. In addition the , reliable messaging middleware handles 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 actually 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 acctually 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.

Thursday, October 23, 2008

How to learn the SOAP version by looking at a soap message

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.

Wednesday, October 22, 2008

How to Get WS-Security working without WS-Addressing in WSF/PHP

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.

Tuesday, October 21, 2008

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 not being set 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.

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.

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.

image

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.

Wednesday, October 15, 2008

How to build PHP from source

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. 

img1

Next, open visual studio command prompt and add binary-tools\bin directory to the path.

img2

Now, go to the PHP source extract directory and type,

buildconf.bat

Then run

cscript /nologo configure.js --help

img3

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.

Friday, September 19, 2008

Integrating PHP CMS Systems with Web Services

There are many PHP CMS Frameworks which provide the capability to easily handle a quality web site which needs daily maintenance. Drupal , Joomla are two such CMS frameworks. These are grate tools for building web sites and managing content. How ever they are functioning in isolation.  When a site grows big, these systems happen to have a lot of valuable data that needs to be integrated with other enterprise systems in order to add business value.

For example consider an enterprise which has build its main web site using one of these tools and has many registered users to this site. Now the enterprise wants to incorporate these users to another application which the enterprise is running, because it wants to provide single sign on capability without having make the users go through another tiresome registration workflow. Also think a scenario where this other system is running on java or .net.

One obvious solution would be to share the database used by the CMS framework for the other application. But such a thing would add many complexities and would require one of the systems to be changed which is not doable in many situations. Now if the other system provides some programmable API or a web services API, then there is an elegant way to solve this integration problem.

With the availability of WSF/PHP  Data Services solution, now you have an easy way to overcome such problems. You can exposed data manipulation operations of the CMS database as web services using WSF/PHP Data Services. Now the two systems can talk to each other using their respective web services and clients, and you have a beautifully integrated solution. 

Thursday, September 18, 2008

Debugging PHP Web Services

One of the difficulties of doing distributed computing, is the difficulty of debugging when things are not going well. It is no exception for Web Services. Since messages are exchanged between services, clients, we have to have some mechanisms  to capture messages, view the soap messages exchanged, some known error messages etc.

Capturing Messages

One of the most well known technique in debugging web services calls is to  some tcp message capture tool to capture the messages exchanged. There are few such good tools for this task.

1. TCPMON tool from apache

             This is a very simple and easy to use tool which has very wide adoption and is quite popular among developers. You can download this tool from apache tcpmon site. 

2. SOAP UI

            This is another popular tool for debugging and developing SOAP based applications. This tool is able to generate request SOAP message for a given WSDL where you fill out the values and send a valid soap request and response. This is a very useful tool to get started with Web Services. You can download soap UI from soapui.org

3.   Ethereal

         This is another tool that is quite useful is capturing and analyzing messages. http://thud.ethereal.com/

Using debugging functions from framework

you can you framework provided functions for debugging. For example WSF/PHP provides two functions getLastRequest() and getLastResponse() on the WSClient class which returns the exchanged request and response messages. Also it provides functions to obtains the returned HTTP headers. Using these, you can also do some debugging.

Logging

Logging is another useful techniques to idenfity possible problems. You can look as the wsf_php_client.log and wsf_php_server.log files and get an idea of what went wrong. If you are not able to trace what's wrong using the logs , you can post your problem with the appropriate log messages to the forum  and get support.

Using Known Error Messages

Another useful technique is to go through the known set of error messages to locate what went wrong. In WSF/PHP, here are some of the error messages you can get.

Monday, September 15, 2008

Implementing Rest Service and Client with WSF/PHP

WSO2 WSF/PHP 2.0.0 has support for HTTP verbs GET,POST,DELETE and PUT in its REST support alone with the ability to support custom URL mappings. Lets have a look at the WSF/PHP REST API and how to implement a simple client and service.

Usually, a REST system is build around CRUD ( Create, Read, Update, Delete ) model.

An HTTP POST Request is a creation of a resource. Similarly a GET request is reading, PUT request is updating and DELETE request is deleting.

You can find details of a design of a complex REST system here.

Implementing a PHP Web Service that can expose its operations as REST operations.

For exposing operations as REST operations, WSService constructor provides the option RESTMapping to specify each operation with its corresponding HTTP method and Custom URL that is mapped to the operation.

Lets consider an example.  Consider we have an operations createUserAccount, updateUserAccount, deleteUserAccount, and readUserAccount as the operations of a simple service called ManageUserAccounts.php

Then out operations map would be like

   1: $operations = array("createUserAccount" => "createAccount",


   2:                "updateUserAccount"=>"updateAccount",


   3:                 "deleteUserAccount"=>"deleteAccount",


   4:             "readUserAccount"=>"getAccount");




Here, the actual php functions implementing the business logic are  createAccount, updateAccount, deleteAccount and getAccount.



Now we can map these operations to an HTTP method and a custom URL, so that we can execute these same operations without having to use SOAP. 





   1: $restmap = array ("createUserAccount"=> array("HTTPMethod"=>"POST","RESTLocation"=> "users"),


   2:           "updateUserAccount"=> array("HTTPMethod"=>"PUT","RESTLocation"=> "users"),


   3:           "deleteUserAccount"=> array("HTTPMethod"=>"DELETE","RESTLocation"=> "users"),


   4:           "readUserAccount"=> array("HTTPMethod"=>"GET","RESTLocation"=> "users"));




Note how HTTPMethod is used to specify the HTTP Method that will be used to invoke each operation. For example, we will be using POST method to  invoke "createUserAccount" operation. 



RESTLocation option is used to specify a portion of a URL which will makeup the final URL of the operation. For example, if our service URL  is "http://localhost/samples/ManageUserAcconts.php" then, since we have set "users" as our RESTLocation, the final URL that will make the endpoint would be "http://localhost/samples/ManageUserAcconts.php/users". Note how I have used the same RESTLocation for all four operations. WSF/PHP is able to identify the correct operation using the HTTPMethod when the URL is the same.



Implementing the client



WSClient class which is the Client API in WSF/PHP API enables you to make use of  HTTP verbs POST,GET,DELETE and PUT when making a REST style operation invocation. 



First you need to know the REST endpoint where the resource is located. Consider we are invoking the "readUserAccount'' function defined in above service. Then our endpoint URL is  "http://localhost/samples/ManageUserAcconts.php/users" and HTTPMethod is GET. You can do this request using WSClient as well as using the Web Browser.





   1:     $client = new WSClient( array("to" => "http://localhost/samples/ManageUserAccounts.php/users",


   2:                                   "useSOAP" => FALSE,


   3:                                   "HTTPMethod" => "GET"));


   4:  


   5:     /** Request Payload String is the XML String send as argument to the operation, 


   6:         In this case, it will be send in query string */


   7:                 


   8:     $responseMessage = $client->request($requestPayloadString);




Similarly you can invoke other operations as well.  I will discuss more details in another blog post.