SOA: Building Service Providers and Service Requestors

Exclusive offer: get 100% off this eBook here
SOA and WS-BPEL

SOA and WS-BPEL — Save 100%

Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook

$29.99    $0.00
by Yuli Vasiliev | April 2010 | .NET BPEL Microsoft SOA Web Services

In this article by Yuli Vasiliev, author of the book SOA and WS-BPEL, we will learn how to how to use the PHP SOAP Extension to build a service requestor and service provider, using the request-response message exchange pattern.

Depending on the interaction scenario in which a Web service is involved, it can either act as a service provider or a service requestor. In the following sections, you will see how to build a Web service provider and a requestor that will consume the service provider.

To start with, let's look at a simple example. Suppose that you need to implement an application based on Web services that performs the following sequence of steps:

  1. Receives a purchase order (PO) document in XML format
  2. Validates a PO against the appropriate XML schema
  3. Stores a PO in the database
  4. Sends a response message to the requestor

In a real-world situation, to build such an application, you would have to design more than one service and pull these services together into a composite solution. However, for simplicity's sake, the example discussed here uses the only service to handle all of the above tasks.

Of course, the above service would be only a part of an entire real-world solution. A service requestor sending a PO document for processing to this service would act as a service provider itself towards another requestor, or would be part of a composite service built, for example, with WS-BPEL.

Diagrammatically, the scenario involving the PO Web service that performs the tasks described above might look like the following figure:

SOA-Building Service Providers and Service Requestors

Here is the detailed explanation of the steps in the figure:

  • Step 1: The service requestor sends a PO XML document wrapped in a SOAP envelope to the service provider.
  • Step 2: The service provider extracts the PO document received from the SOAP envelope and validates the extracted PO against the appropriate XML schema.
  • Step 3: The service provider stores the validated PO document in the database.
  • Step 4: The service provider sends the response message to the service requestor, informing it if the operations being performed have completed successfully or not.

To build the PO Web service depicted in the previous figure, you need to accomplish the following five general steps:

  1. Set up a database to store incoming PO documents
  2. Develop a PHP handler class implementing the PO Web service logic
  3. Design an XML schema to validate incoming PO documents
  4. Design a WSDL document describing the PO Web service to its requestors
  5. Build a SOAP server to handle incoming messages carrying POs

The following sections take you through each of the above steps. First, you will see how to create a simple PO Web service that actually performs no validation. Then, you will learn how the XML Schema feature can be used with WSDL to define types in messages being transmitted, making sure that transmitted data is valid with respect to a specific XML schema.

Setting Up the Database

B efore we go any further, let's take a moment to set up the database required for this example. This example assumes that you are using Oracle Database Express Edition (XE)—a free edition of Oracle Database, or any other edition of Oracle database.

You can download a copy of Oracle Database from the Download page of the Oracle Technology Network (OTN) Website at http://www.oracle.com/technology/software/index.html. For this particular example, Oracle is used because it provides native support for XML, which makes it easier for you to get the job done, allowing you to concentrate on using the PHP SOAP extension while building the application.

To keep things simple, this section actually discusses how to create a minimal set of the database objects required only to store incoming PO documents.

The Oracle XML Schema is part of the Oracle XML DB, which is a set of Oracle XML features available in any edition of Oracle Database by default.

With Oracle database, you have several options when it comes to creating, accessing and manipulating the database objects. You can use both the graphical and command-line tools shipped with Oracle Database. As for Oracle Database XE, you might use the Oracle Database XE graphical user interface, a browser-based tool that allows you to administer the database.

However, to create the database objects required for this example, it is assumed that you will make use of Oracle SQL*Plus, a command-line SQL tool, which is installed by default with every Oracle database installation.

With SQL*Plus, you interact with the database server by entering appropriate SQL statements at the SQL> prompt.

Assuming that you have an Oracle database server installed and running, launch SQL*Plus and then follow these steps:

Set up a database account that will be used as a container for the database objects by issuing the following SQL statements:

//connect to the database as sysdba to be able to create a new
account
CONN /as sysdba

//create a user identified as xmlusr with the same password
CREATE USER xmlusr IDENTIFIED BY xmlusr;

//grant privileges required to connect and create resources
GRANT connect, resource TO xmlusr;

Issue the following SQL statements to create a table that will be used to store PO XML documents:

//connect to the database using the newly created account
CONN xmlusr/xmlusr;
//create a purchaseOrders table to be used for storing POs
CREATE TABLE purchaseOrders(
doc VARCHAR2(4000)

);

As you can see, the purchaseOrders table created by the above statement contains only one column, namely doc of VARCHAR2. Using the VARCHAR2 Oracle data type is the simplest option when it comes to storing XML documents in an Oracle database. In fact, Oracle provides much more powerful options for storing XML data in the database.

Developing the PHP Handler Class

N ow that you have set up the database to store the incoming PO documents, it's time to create the PHP code that will perform just that operation: storing incoming POs into the database. Consider the purchaseOrder PHP class containing the PO Web service underlying logic. It is assumed that you will save this class in the purchaseOrder.php file in the WebServices\ch2 directory within the document directory of your Web server, so that it will be available at http://localhost/ WebServices/ch2/purchaseOrder.php.

<?php
//File purchaseOrder.php
class purchaseOrder {
function placeOrder($po) {
if(!$conn = oci_connect('xmlusr', 'xmlusr', '//localhost/xe')){
throw new SoapFault("Server","Failed to connect to
database");
};
$sql = "INSERT INTO purchaseOrders VALUES(:po)";
$query = oci_parse($conn, $sql);
oci_bind_by_name($query, ':po', $po);
if (!oci_execute($query)) {
throw new SoapFault("Server","Failed to insert PO");
};
$msg='<rsltMsg>PO inserted!</rsltMsg>';
return $msg;
}
}
?>

Looking through the code, you may notice that the purchaseOrder class actually contains the only method, namely placeOrder. As its name implies, the placeOrder method is responsible for placing an incoming PO document. What this method actually does is take a PO XML document as the parameter and then store it in the purchaseOrders table created in the preceding section. Upon failure to connect to the database or execute the INSERT statement, the placeOrder method stops execution and throws a SOAP exception.

Another important point to note here is that the placeOrder method doesn't contain any code required to validate an incoming PO document. For simplicity, this example assumes no validation for the moment.

SOA and WS-BPEL Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook
Published: September 2007
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Designing the WSDL Document

To expose the functionality of the purchaseOrder PHP class discussed in the preceding section as a Web service, you first need to create a WSDL document that will describe that Web service. Here is the WSDL that might serve this purpose. It is assumed that you will save this document as po.wsdl in the WebServices/wsdl directory within the document directory of your Web server.

<?xml version="1.0" encoding="utf-8"?>
<definitions name ="poService"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace=
"http://localhost/WebServices/wsdl/po.wsdl">
<message name="getPlaceOrderInput">
<part name="body" element="xsd:string"/>
</message>
<message name="getPlaceOrderOutput">
<part name="body" element="xsd:string"/>
</message>
<portType name="poServicePortType">
<operation name="placeOrder">
<input message="tns:getPlaceOrderInput"/>
<output message="tns:getPlaceOrderOutput"/>
</operation>
</portType>
<binding name="poServiceBinding" type="tns:poServicePortType">
<soap:binding style="document" transport=
"http://schemas.xmlsoap.org/soap/http"/>
<operation name="placeOrder">
<soap:operation
soapAction="http://localhost/WebServices/ch2/placeOrder"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="poService">
<port name="poServicePort" binding="tns:poServiceBinding">
<soap:address
location="http://localhost/WebServices/ch2/SOAPserver.php"/>
</port>
</service>
</definitions>

As you may notice, the getPlaceOrderInput message described in this document consists of a single part called body, which represents an element of xsd:string. Actually, the body part used here represents the parameter being passed to the placeOrder method of the purchaseOrder class discussed in the preceding section. So, this WSDL document implies that an incoming PO XML document will be passed from a service consumer to the PO Web service as a string.

As you no doubt have realized, the string XSD type is used in this example for simplicity's sake.

Building the SOAP Server

N ow that you have created the WSDL definition document describing the PO Web service, the next step is to create a SOAP server that will be responsible for handling and transmitting SOAP messages via HTTP. Save the following PHP script as SoapServer.php in the WebServices/ch2 directory within the document directory of your Web server.

<?php
//File: SoapServer.php
require_once "purchaseOrder.php";
$wsdl= "http://localhost/WebServices/wsdl/po.wsdl";
$srv= new SoapServer($wsdl);
$srv->setClass("purchaseOrder");
$srv->handle();
?>

At the beginning of this script you add the contents of the purchaseOrder.php script discussed in the Developing the PHP Handler Class section earlier in this article. Then, you create an instance of the SoapServer class.

The SoapServer class, as well as SoapClient and SoapFault classes discussed in the next section, belongs to the PHP's SOAP extension library, which is not enabled by default. To enable the SOAP extension on a Unix-like platform, you need to recompile your PHP installation with the configure option --enable-soap. If you are a Windows user, you need to append the extension =php_soap.dll to the list of extensions in the php.ini configuration file.

Once you have created an instance of SoapServer, you can export the methods of the PHP handler class stored in the purchaseOrder.php script. This is done with the help of the setClass method of the SoapServer instance.

Finally, you call the handle method of SoapServer, which is responsible for handling and processing SOAP requests, calling methods of the handler class, and sending responses back to service consumers.

Building the Service Requestor

B efore you can test the PO Web service built as discussed in the preceding sections, you need to build a service requestor that will interact with the service. Here is a simple client to test the PO Web service. You may save this script in any directory. However, for simplicity's sake you might save it in the same directory as all the other scripts discussed previously.

<?php
//File: SoapServer.php
require_once "purchaseOrder.php";
$wsdl= "http://localhost/WebServices/wsdl/po.wsdl";
$srv= new SoapServer($wsdl);
$srv->setClass("purchaseOrder");
$srv->handle();
?>

As you can see, this script loads a PO document from the purchaseOrder.xml file, which is supposed to be in the same directory as the script. Then, it creates an instance of the SoapClient class, passing a URI of the WSDL document to be used, as the parameter. Note that you use the same WSDL document you used for the server discussed in the preceding section. Finally, the script calls the placeOrder remote function as a method of the newly created SoapClient instance, surrounding that call in a try block. If something goes wrong during the placeOrder execution and a SoapFault exception is thrown, the catch block catches it.

A simplified version of a PO document stored in the purchaseOrder.xml file being used in this example might look as follows:

<purchaseOrder >
<pono>108128476</pono>
<billTo>
<name>Tony Jamison</name>
<street>24 Johnson Road</street>
<city>Big Valley</city>
<state>VA</state>
<zip>23032</zip>
<country>US</country>
</billTo>
<shipTo>
<name>Janet Thomson</name>
<street>11 Maple Street</street>
<city>Small Valley</city>
<state>VA</state>
<zip>23037</zip>
<country>US</country>
</shipTo>
<items>
<item>
<partId>743</partId>
<quantity>4</quantity>
<price>15.50</price>
</item>
<item>
<partId>235</partId>
<quantity>7</quantity>
<price>15.75</price>
</item>
</items>
</purchaseOrder>

In a real-world situation, a PO XML document might be derived from different sources, not necessarily from a file. For example, it might be created on the fly (dynamically) by a PHP script, with the help of the DOM API that is part of the PHP core.

Testing the Service

N ow you are ready to test the PO Web service. To do this, you simply need to point your browser at the service requestor discussed in the preceding section. If you saved the SoapClient.php script in the WebServices/ch2 directory within the document directory of your Web server, enter the following URL in the address box of your browser: http://localhost/WebServices/ch2/SoapClient.php.

If everything goes as planned, you will see a PO inserted! message in your browser. Otherwise, a SOAP fault message appears. For example, if the placeOrder method of the purchaseOrder class fails to connect to the database, you will see an error message that will look as follows:

Failed to connect to database

Turning back to the placeOrder method of the purchaseOrder class discussed in the Developing the PHP Handler Class section earlier, you may notice that it also throws a SOAP exception upon failure to insert the received PO into the database.

If the request was successful, the purchaseOrders table was created as discussed in the Setting Up the Database section earlier should contain one more row. To make sure it does so, you can issue the following query from Oracle SQL*Plus or any other command-line tool you use to communicate with the database:

CONN xmlusr/xmlusr

SELECT * FROM purchaseOrders;

When executed, the above SELECT statement should output the string representing the same PO XML document as the one shown in the Building the Service Requestor section earlier. If so, this means the PO Web service has worked successfully.

Summary

In this article, we saw how creating service providers and service requestors with the PHP SOAP extension is quite easy in most cases—we simply manipulated predefined SOAP classes.

If you have read this article you may be interested to view :

SOA and WS-BPEL Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook
Published: September 2007
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Yuli Vasiliev

Yuli Vasiliev is a software developer, freelance author, and consultant currently specializing in open-source development, Oracle technologies, and service-oriented architecture (SOA). He has over 10 years of software development experience as well as several years of technical writing experience. He wrote a series of technical articles for Oracle Technology Network (OTN) and Oracle Magazine.

Contact Yuli Vasiliev

Books From Packt

SOA   Patterns with BizTalk Server 2009
SOA Patterns with BizTalk Server 2009

SOA Governance
SOA Governance

Business Process Execution Language for Web Services 2nd Edition
Business Process Execution Language for Web Services 2nd Edition

BPEL Cookbook: Best Practices for SOA-based   integration and composite applications development
BPEL Cookbook: Best Practices for SOA-based integration and composite applications development

RESTful Java Web Services
RESTful Java Web Services

Oracle Web Services Manager
Oracle Web Services Manager

ASP.NET 3.5 Social Networking
ASP.NET 3.5 Social Networking

Microsoft Dynamics AX 2009 Programming:   Getting Started
Microsoft Dynamics AX 2009 Programming: Getting Started

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software