torsdag, september 01, 2005

HelloBPEL

Många har säkert sett The Evolution of a Programmer och tyckte det var komiskt hur mycket kod man kan skriva för att få ut "Hello World" på skärmen. Här är Hello BPEL.

En SOA bygger på meddelanden, tjänster och processer och det gäller även om man ska implementera något så simpelt som Hello World. För att köra det här exemplet krävs en ESB (ex. CapeClear, ActiveBPEL).

Meddelandet
Vi börjar med att definiera meddelandetyperna i XML Schema även om man normalt sett börjar med processen och därefter meddelandena.

Hello.xsd



<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://swenug.com/bpel-demo/Hello.xsd"
xmlns="http://swenug.com/bpel-demo/Hello.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">


I schemat skapar man typerna som ska ingå i ett meddelande.


<xsd:complexType name="HelloRequestType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>


I det här fallet så definierar vi en typ för anropet och ett för svaret.


<xsd:complexType name="HelloResponseType">
<xsd:sequence>
<xsd:element name="Greeting" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>




Tjänsten
Tjänsten som deklareras i WSDL innehåller en import av meddelandetyperna, meddelandena själva, port, operation, address och bindning som tillsammans skapar tjänstekontraktet.

HelloService.wsdl



<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="http://swenug.com/bpel-demo/HelloService.wsdl"
xmlns:tns="http://swenug.com/bpel-demo/HelloService.wsdl"
xmlns:htd="http://swenug.com/bpel-demo/schema"
xmlns:imp="http://swenug.com/bpel-demo/Hello.xsd"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">


Ett WSDL-kontrakt börjar alltid med en typdeklaration.
Här importeras typerna från schemat.


<wsdl:types>
<xsd:schema
targetNamespace="http://swenug.com/bpel-demo/schema"
xmlns:imp="http://swenug.com/bpel-demo/Hello.xsd"
xmlns:htd="http://swenug.com/bpel-demo/schema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="HelloRequest" type="imp:HelloRequestType"/>
<xsd:element name="HelloResponse" type="imp:HelloResponseType"/>
<xsd:import
namespace="http://swenug.com/bpel-demo/Hello.xsd"
schemaLocation="http://swenug.com/bpel-demo/v.0.2.1/Hello.xsd"/>
</xsd:schema>
</wsdl:types>


Sedan deklareras själva meddelandena som ska användas i operationerna.
Typerna ovan är delar (parts) av ett meddelande.


<wsdl:message name="HelloRequestMessage">
<wsdl:part element="htd:HelloRequest" name="Salut"/>
</wsdl:message>
<wsdl:message name="HelloResponseMessage">
<wsdl:part element="htd:HelloResponse" name="Greeting"/>
</wsdl:message>


I WSDL är PortType som ett Interface är i C# eller Java.
Operation kan liknas vid en metod.


<wsdl:portType name="HelloPortType">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:HelloRequestMessage"/>
<wsdl:output message="tns:HelloResponseMessage"/>
</wsdl:operation>
</wsdl:portType>


Bindningen anger till den fysiska delen av kontraktet,
på vilket sätt som meddelandena ska paketeras när de passerar porten.


<wsdl:binding name="HelloBinding" type="tns:HelloPortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHello">
<soap:operation soapAction="urn:Hello#sayHello">
<wsdl:input>
<soap:body parts="Salut" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body parts="Greeting" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>


Den här delen av kontraktet binder porttypen/interfacet till en fysisk port.


<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloBinding" name="HelloPort">
<soap:address location="http://servername/Hello"/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>



Processen
Det är processen som ska göra jobbet, d v s implementera tjänsten. Innan vi skapar arbetsflödet i BPEL så måste vi ha en länk till kontraktet. Den skapas i en ny WSDL-fil.

HelloPartnerLinks.wsdl


<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="http://swenug.com/bpel-demo/HelloPartnerLinks.wsdl"
xmlns:tns="http://swenug.com/bpel-demo/HelloPartnerLinks.wsdl"
xmlns:ns="http://swenug.com/bpel-demo/HelloService.wsdl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/">

<wsdl:import namespace="http://swenug.com/bpel-demo/HelloService.wsdl"
location="http://swenug.com/bpel-demo/v.0.2.1/HelloService.wsdl"/>


Här knyter vi ihop BPEL med kontraktet.


<plnk:partnerLinkType name="HelloLink">
<plnk:role name="ServiceProvider">
<plnk:portType name="tns:HelloPortType"/>
</plnk:role>
</plnk:partnerLinkType>

</wsdl:definitions>



Nu är det dags för själv processen att beskrivas i BPEL.

HelloBPEL.bpel


<?xml version="1.0"?>
<bpws:process name="Hello"
targetNamespace="http://swenug.com/bpel-demo/HelloBPEL.bpel"
xmlns:tns="http://swenug.com/bpel-demo/HelloBPEL.bpel"
xmlns:plt="http://swenug.com/bpel-demo/HelloPartnerLinks.wsdl"
xmlns:hs="http://swenug.com/bpel-demo/HelloService.wsdl"
xmlns:htd="http://swenug.com/bpel-demo/schema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">


Importera information om länken till kontraktet.


<bpws:import
location="http://swenug.com/bpel-demo/v.0.2.1/HelloPartnerLinks.wsdl"
namespace="http://swenug.com/bpel-demo/HelloPartnerLinks.wsdl"
importType="http://schemas.xmlsoap.org/wsdl/">
</bpws:import>


Nu är det dags att sätta namn på länken till tjänstekontraktet
så det kan användas för åtkomst senare.


<bpws:partnerLinks>
<bpws:partnerLink myRole="ServiceProvider" name="HelloClient"
partnerLinkType="plt:HelloLink">
</bpws:partnerLink>
</bpws:partnerLinks>


Processen behöver definiera variabler. De här två i scopet av hela processen.


<bpws:variables>
<bpws:variable messageType="hs:HelloRequestMessage"
name="HelloRequestMessage" />
<bpws:variable messageType="hs:HelloResponseMessage"
name="HelloResponseMessage" />
</bpws:variables>


Nu till själva flödet.


<bpws:sequence>


Receive är starten på processen som även deklarerar
att en ny instans av arbetsflödet ska skapas.
Varje anrop in som inte görs till en existerande instans,
skapar istället en ny.


<bpws:receive partnerLink="HelloClient" portType="hs:HelloPortType"
operation="sayHello" variable="HelloRequestMessage" createInstance="yes">
</bpws:receive>


Det här är själva logiken bakom tilldelningen av svarsmeddelande.
Här används ett uttryck som hämtar upp namnet ur meddelandet och
bygger upp ett svar.


<bpws:assign>
<bpws:copy>
<bpws:from expression="concat('Hello ',
bpws:getVariableData('HelloRequestMessage',
'Salut', '/htd:HelloRequest') )"></bpws:from>
<bpws:to variable="HelloResponseMessage" part="Greeting"/>
</bpws:copy>
</bpws:assign>


Det sista som behöver göras är att returnera svaret.


<bpws:reply partnerLink="Hello" portType="hs:HelloPortType"
operation="sayHello" variable="HelloResponseMessage">
</bpws:reply>
</bpws:sequence>
</bpws:process>


Inga kommentarer: