service component architecture for php · • components use php annotations both to declare their...

37
Service Component Architecture for PHP Reusable components and effort-free web services Matthew Peters, IBM Hursley Park [email protected]

Upload: others

Post on 11-Jul-2020

12 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

Service Component Architecture for PHP

Reusable components and effort-free web servicesMatthew Peters, IBM Hursley Park

[email protected]

Page 2: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

1

Background

• IBM Hursley Park, Winchester, UK• http://www5.ibm.com/uk/locations/hursley_explore.html

• 2-3K people

• Services, outsourcing

• Product development: CICS, MQSeries, Java

• Incubator group:

• Porting, experimenting with technologies from Java world, implementing and simplifying in PHP

Page 3: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

2

How to find us

• Google for OSOA

• (Open Service Oriented Architecture)

Page 4: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

3

Agenda

• Two slide-overview• Some simple SCA components (hello world–style)

• Components calling each other locally• Make them all run as web services• (Slides and Zend Studio)

• More SCA:• Interoperability with other web services• Exceptions• Data Structures

• Work in progress: DOJO, JSON-RPC and SCA• Summary, Futures and Links

Page 5: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

4

SWG AB IncubatorsService Component Architecture

for PHP• SCA for PHP allows a PHP programmer to write reusable

components (classes) in PHP, which can be called either locally, or remotely via Web Services, with an identical interface.

• Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose as a service. Business logic is kept separate from interface and dependencies.

• Deploying a PHP component as a web service can be as simple as copying it into a web server’s document root.

Page 6: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

5

Making your component reusable

• Do not entangle the business logic with the “wiring”

1. Be flexible about how you are called• Expose as many ‘bindings’ as needed – make sure your business logic does not

need to know how it was called

2. Be flexible about your dependencies• Declare the dependencies – but make sure your business logic does not need to

know how to resolve these • Ideally get something else to “wire up” the components (Inversion of Control;

Dependency Injection patterns)

JSON-RPC binding

A component,

containing

business logic

A local component,

Same call stack

A web service

2. Be flexible about your dependencies1. Be flexible about

how you are called

Local binding

Web service binding

Page 7: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

6

Four scenarios

1. One component called locally

2. One component calling two others

3. Make the single component expose a Web service binding

4. Make them all use web services

• Same interface, minimal effort

Page 8: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

7

Scenario 1. Simplest

• A client script calling one local component

• What does the simplest SCA component look like?

GreetingComponentclient

Page 9: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

8

Our first simple SCA component

• A PHP class

• @service annotation

• include for SCA.php

<?php

include 'SCA/SCA.php';

/*** @service*/class GreetingComponent{

public function greet($name) {

return 'hello ' . $name;}

}?>

GreetingComponent

Page 10: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

9

Calling an SCA component from a client script

• Client script • Includes SCA.php• But is not itself a

component

• Uses SCA::getService()• getService takes a

path• Absolute or relative• Relative paths are

resolved against the location of the script

• getService returns a ‘proxy’ object:

• Enforces pass-by-value

<?php

include 'SCA/SCA.php';

$service = SCA::getService('./GreetingComponent.php');

echo $service->greet('PHP');

?>

GreetingComponentclient

"hello PHP"

Page 11: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

10

Scenario 2. Multiple

• A local component calling other local components• How are the dependencies wired up?

ReversingComponent

ReversedGreeting

Component

GreetingComponent

client

"PHP olleh"

Page 12: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

11

Add a second component

• Like GreetingComponent:• @service

• Include for SCA.php

<?php

include 'SCA/SCA.php';

/*** @service*/

class ReversingComponent{

function reverse ($in){

return strrev ($in);}

}

?>

ReversingComponent

Page 13: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

12

Dependencies• Dependencies are declared• annotated with @reference

• The instance variable following will be assigned a proxy

• Hence needs to be public• Initialised before any

business logic

• @binding.php• indicates how to find the

component• and that it is local• same rules as getService

<?php

include 'SCA/SCA.php';

/*** @service*/class ReversedGreetingComponent{/**

* @reference* @binding.php GreetingComponent.php*/public $greeting_component;

/*** @reference* @binding.php ReversingComponent.php*/public $reversing_component;

public function greet($name){

$greeting = $this-> greeting_component->greet($name);return $this->reversing_component->reverse($greeting);

}}

?>

ReversedGreeting

Component

Page 14: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

13

What have we got so far?

• Sample call stack:

ReversingComponent

ReversedGreeting

Component

GreetingComponent

client

reverse( $in ) C:\Program Files\Apache Group\Apache2\htdocs\Konferenz\ReversingComponent.php line 13 __call( $method_name, $arguments ) c:\php\PEAR\SCA\SCA_LocalProxy.php line 109 greet( $name ) C:\Program Files\Apache Group\Apache2\htdocs\Konferenz\ReversedGreetingComponent.php line 24 __call( $method_name, $arguments ) c:\php\PEAR\SCA\SCA_LocalProxy.php line 109 main( ) C:\Program Files\Apache Group\Apache2\htdocs\Konferenz\client2.php line 7

SCA_Localproxy

breakpoint

"PHP olleh"

Page 15: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

14

Scenario 3. Web Service

• A client script calling one remote component

• How to expose a web service binding

GreetingComponentclient

= SOAP Web service request/response

Page 16: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

15

Exposing a web service binding• @binding

• Expose a web service binding

• Public methods are in the interface

• @param/@return• Need more information

about each method

<?php

include 'SCA/SCA.php';

/*** @service* @binding.ws*/

class GreetingComponent{

/*** @param string $name* @return string*/

public function greet($name) {

return 'hello ' . $name;}

}?>

GreetingComponent

= SOAP Web service request/response

Page 17: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

16

Generating the WSDL

• Generated in response to HTTP GET with ?wsdl• http://www.example.com/GreetingComponent.php?wsdl

• Do it in a browser

• file_get_contents('http://www.example.com/GreetingComponent.php?wsdl');

• Currently cached in the same directory as the component• http://www.example.com/GreetingComponent.wsdl

• (in future need to do something different to avoid need for write access into htdocs)

Page 18: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

17

Generated WSDL

• Document/literal wrapped style• Message

formats are explicit within the schema

<?xml version="1.0" encoding="UTF-8"?><definitions xmlns="http://schemas.xmlsoap.org/wsdl/"

xsi:type="tDefinitions«xmlns:tns2="http:// GreetingComponent"xmlns:tns="http://schemas.xmlsoap.org/wsdl/"xmlns:tns3="http://schemas.xmlsoap.org/wsdl/soap/"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"targetNamespace="http://GreetingComponent"><types><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://GreetingComponent"><xs:element name="greet">

<xs:complexType><xs:sequence>

<xs:element name=“name" type="xs:string" nillable="true"/></xs:sequence>

</xs:complexType></xs:element><xs:element name="greetResponse">

<xs:complexType><xs:sequence>

<xs:element name="greetReturn" type="xs:string" nillable="true"/></xs:sequence>

</xs:complexType></xs:element>

</xs:schema></types>

...

Page 19: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

18

Generated WSDL

• message …

• post …

• binding …

...<message name="greetRequest"><part name="greetRequest" element="tns2:greet"/>

</message><message name="greetResponse"><part name="return" element="tns2:greetResponse"/>

</message><portType name="GreetingComponentPortType"><operation name="greet"><input message="tns2:greetRequest"/><output message="tns2:greetResponse"/>

</operation></portType><binding name="GreetingComponentBinding" type="tns2:GreetingComponentPortType"><operation name="greet"><input><tns3:body xsi:type="tBody" use="literal"/>

</input><output><tns3:body xsi:type="tBody" use="literal"/>

</output><tns3:operation xsi:type="tOperation" soapAction=""/>

</operation><tns3:binding xsi:type="tBinding" transport="http://schemas.xmlsoap.org/soap/http"

style="document"/></binding>...

Page 20: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

19

Generated WSDL• Location attribute is decided once the file is in place

• Currently using the URL to determine the location with respect to the document root

• (in future need to do something different to cope with proxies, rewriting, firewalls)

• Ends with a distinctive comment• Special handling of exceptions when one component talks to another

...<service name="GreetingComponentService">

<port name="GreetingComponentPort" binding="tns2:GreetingComponentBinding"><tns3:address xsi:type="tAddress" location="http://www.example.com/GreetingComponent.php"/>

</port></service>

</definitions><!-- this line identifies this file as WSDL generated by SCA for PHP. Do not remove -->

Page 21: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

20

Calling a remote SCA component from a script

• SCA::getService() takes the location of the WSDL• Once again, $service is a

proxy: SCA_SoapProxy

• Proxy contains within it an instance of the ext/SOAP client

• Location can be a URL…• In which case the soap

extension will probably cache it

• Location can be a path• Relative paths resolved

against location of script

<?php

include 'SCA/SCA.php';

$service = SCA::getService('http://www.example.com/GreetingComponent.wsdl');

echo $service->greet();

?>

Greeting

Componentclient

= SCA_SoapProxy

Page 22: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

21

Sample Soap request

• Document/literal wrapped, so <greet> element enclosing <name> element

<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body>

<tns:greet xmlns= "http://GreetingComponent"xmlns:tns= "http://GreetingComponent"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="greet"><name>PHP</name>

</tns:greet></SOAP-ENV:Body>

</SOAP-ENV:Envelope>

Page 23: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

22

Scenario 4. Multiple web service

• Everything separated

ReversingComponent

ReversedGreeting

Component

GreetingComponent

client

= SOAP Web service request/response

Page 24: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

23

A second remote component

• Annotations• @binding• @param• @return

• And generate WSDL as before

<?php

include 'SCA/SCA.php';

/*** @service* @binding.ws*/

class ReverseComponent{

/*** @param string $in* @return string*/function reverse ($in){

return strrev ($in);}

}?>

ReversingComponent

Page 25: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

24

Remote dependencies

• @binding.wsfor remote component

• locates wsdl

<?phpinclude 'SCA/SCA.php';

/*** @service* @binding.ws*/class ReversedGreetingComponent{/**

* @reference* @binding.ws GreetingComponent.wsdl*/public $greeting_component;

/*** @reference* @binding.ws ReversingComponent.wsdl*/public $reversing_component;/*** @param string $name* @return string*/

public function greet($name){

$greeting = $this-> greeting_component->greet($name);return $this->reversing_component->reverse($greeting);

}}?>

ReversedGreeting

Component

Page 26: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

25

What have we got now?• What have we achieved?

• Client <–> local <-> local • Client <-> remote <-> remote

• What had to change?• Arguments to getService(), or @binding.php to @binding.ws• Annotatations to describe the interface in more detail• Generating WSDL on demand; otherwise deployment is just copying the component

• But the business logic remains unchanged

ReversingComponent

ReversedGreeting

Component

GreetingComponent

client

SOAP Web service request/response

Page 27: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

26

Interlude

• “But, you have to change the files themselves…”• True, but changing an annotation in an interpreted file – is that different from a line in a config file?

• Essential point is that “wiring” and business logic are separated• Same file, but in different worlds• Wiring is declarative, in annotations• Business logic is imperative, in code

Page 28: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

38

Futures

• Annotation overriding• Changing service targets, bindings, properties from outside

• PHP classes rather than xsds for data structures

• Simple database services

• Other bindings• Atompub, REST (XML and JSON), RSS

Page 29: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

39

DOJO, JSON-RPC and SCA• DOJO is a user interface widget set written in JavaScript

• Can talk back to the server asynchronously - AJAX style• Can use JSON-RPC to do so

• JSON = JavaScript Object Notation• Like a simplified XML • Name/value pairs• { for structure• [ array

• A JSON-RPC interface can be defined in SMD = Service Method Description• Like a simplified WSDL• Also written in JSON

• SCA components can expose a JSON-RPC binding too

Page 30: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

40

Page 31: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

41

A component exposing a JSON binding

• @binding.jsonrpc

• Generates .smd

• <url>?smd

• smd = service method description

<?phpinclude 'SCA/SCA.php';/*** @service* @binding.jsonrpc*/class HelloService{

/*** @param string $name The name to say hello to* @return string The string hello <name>*/public function sayHello ($name){

return ‘hello ‘ . $name;}

}?>

Page 32: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

42

HelloService.php?smd

• Defines a service that has:• One method sayHello(), with …• One parameter, name

{"SMDVersion":".1","serviceType":"JSON-RPC","serviceURL":"http://localhost/Samples/JsonRpc/hello/HelloService.php","methods": [ {

"name":"sayHello","parameters": [ {

"name":"name","type":"string“

} ],"return": {"type":"string"}

} ]}

Page 33: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

43

A DOJO function to call sayHello

• Obtain .smd

• Issue the call

function sayHello(){

var SCA = new dojo.rpc.JsonService({smdUrl: "HelloService.php?smd"});var inputfield = document.getElementById("hellotext").value;SCA.sayHello(inputfield).addCallback(handleResponse);

}

Page 34: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

44

JSON-RPC - POST• POST Style - Request

• POST Style - Response

POST /json-rpc/HelloService.php HTTP/1.1

Host: localhost:8081

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7

Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

Accept-Language: en-us,en;q=0.5

Accept-Encoding: gzip,deflate

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Keep-Alive: 300

Connection: keep-alive

Content-Type: application/json-rpc

Content-Length: 48

Pragma: no-cache

Cache-Control: no-cache

{"params":["Hello!"],"method":"sayHello","id":1}

HTTP/1.1 200 OK

Date: Tue, 03 Oct 2006 18:14:35 GMT

Server: Apache/2.0.55 (Win32) PHP/5.2.0RC5-dev

X-Powered-By: PHP/5.2.0RC5-dev

Content-Length: 27

Keep-Alive: timeout=15, max=89

Connection: Keep-Alive

Content-Type: application/json-rpc

{“return":"Hello "}

Page 35: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

45

Links

• SCA for PHP homepage• http://osoa.org/display/PHP/SOA+PHP+Homepage

• Discussion Group• http://groups.google.com/group/phpsoa/

• Blog• http://www.ibm.com/developerworks/blogs/page/phpblog

• SDO for PHP• http://www.php.net/sdo

Page 36: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

46

Acknowledgements

• Other members of the SCA for PHP team

• Graham Charters, Megan Beynon, Chris Miller, Caroline Maynard, Simon Laws

• Special thanks to Dmitry Stogov for help with the SOAP extension, serialising and de-serialising SDOs

Page 37: Service Component Architecture for PHP · • Components use PHP annotations both to declare their dependencies on other components, and to define the interface which they expose

47

The end