Straight-Through Data Transformation Example

Use Case

The DEF Corporation's intranet has a Web-based online store through which employees can purchase the company's products. The store's XFORMS-based Web interface registers the order by sending an XML document containing the order details to an asynchronous message queue, which is serviced by a workflow management system. Each incoming message triggers a new workflow instance that retrieves additional information about the employee (by calling a predefined procedure). The workflow then merges the extra information into the XML document by applying an XSL transform. It then submits the transformed order for fulfillment by invoking the Sales Order System's Web Service interface.

Interfaces

Input Document schema

The input document is a string containing an XML document that conforms to the following XML Schema:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://www.def.com/2004/intranet/webstore">
<xsd:element name="web-order">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="header">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="userid" type="xsd:NMTOKEN"/>
<xsd:element name="datetime" type="xsd:dateTime"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="items">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="item">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sku" type="xsd:string"/>
<xsd:element name="qty" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

Functions available from scripting language

Map createMap(IN STRING key, IN STRING value)

Procedures

lookupAccount(IN STRING userId, OUT STRING accountNumber)
transform(IN Document input, OUT Document output, IN STRING transformURI, IN Map parms)

XSL transform

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:in="http://www.def.com/2004/intranet/webstore"
xmlns="http://www.def.com/2004/pub/sales">

<xsl:output method="xml"/>

<!-- The user's account number, passed in as a parameter. -->
<xsl:param name="account-number"/>

<xsl:template match="in:order">
<xsl:element name="sales-order">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

<xsl:template match="in:userid">
<xsl:element name="account-number">
<xsl:value-of select="$account-number" disable-output-escaping="yes"/>
</xsl:element>
</xsl:template>

<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

</xsl:transform>

Web Service Description

The Sales Order Processing system has a Web Service interface defined by the following WSDL:
<?xml version="1.0" encoding="UTF-8"?>
    
<wsdl:definitions targetNamespace="http://www.def.com/2004/pub/sales"
xmlns:impl="http://www.def.com/2004/pub/sales"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xsd:schema targetNamespace="http://www.def.com/2004/pub/sales"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xsd:element name="sales-order">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="header">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="account-number" type="xsd:string"/>
<xsd:element name="datetime" type="xsd:dateTime"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="items">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="item">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="sku" type="xsd:string"/>
<xsd:element name="qty" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>

<wsdl:message name="raiseOrderRequest">
<wsdl:part name="order" element="impl:sales-order"/>
</wsdl:message>

<wsdl:portType name="SalesOrdersPortType">
<wsdl:operation name="raiseOrder" parameterOrder="order">
<wsdl:input name="raiseOrderRequest" message="impl:raiseOrderRequest"/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name="SalesOrdersPortSoapBinding" type="impl:SalesOrdersPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="raiseOrder">
<soap:operation soapAction="http://www.def.com/sales/raiseOrder"/>
<wsdl:input name="raiseOrderRequest">
<soap:body namespace="http://www.def.com/2004/pub/sales" use="literal"/>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="SalesOrders">
<wsdl:port name="SalesOrdersPort" binding="impl:SalesOrdersPortSoapBinding">
<soap:address
location="http://localhost:8080/obeexamples/services/SalesOrders"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Hints

Solution

Process Model Description

EAI workflow diagram

XPDL Process Model

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://www.wfmc.org/2002/XPDL1.0" xmlns:xpdl="http://www.wfmc.org/2002/XPDL1.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:obe="http://obe.sourceforge.net/2005/OBE1.0" xmlns:defws="http://www.def.com/2004/intranet/webstore"
Id="eai" Name="EAI Data Transformation" xsi:schemaLocation="http://www.wfmc.org/2002/XPDL1.0 xpdl-1.0.xsd">
<PackageHeader>
<XPDLVersion>1.0</XPDLVersion>
<Vendor>Open Business Engine</Vendor>
<Created>2004-08-08T21:26:45+0100</Created>
</PackageHeader>
<RedefinableHeader PublicationStatus="UNDER_TEST"/>
<ConformanceClass GraphConformance="NON_BLOCKED"/>
<Script Type="text/x-xpath"/>
<TypeDeclarations>
<TypeDeclaration Id="WebOrder" Name="Web Store Order">
<ExternalReference location="web-order.xsd" xref="order"
namespace="http://www.def.com/2004/intranet/webstore"/>
<Description>This is the order type generated by the internal Web Store portal.</Description>
</TypeDeclaration>
<TypeDeclaration Id="SalesOrder" Name="SalesOrder">
<ExternalReference
location="http://sales.def.com:8080/axis/services/OrderService?wsdl"
xref="SalesOrderType" namespace="http://www.def.com/2004/pub/sales"/>
<Description>This is the type of the Sales Order document accepted by the Sales Order Management system.</Description>
</TypeDeclaration>
<TypeDeclaration Id="Document" Name="XML Document">
<ExternalReference location="java:org.w3c.dom.Document"/>
</TypeDeclaration>
<TypeDeclaration Id="Map" Name="Java Map">
<ExternalReference location="java:java.util.Map"/>
<Description>This type represents the Java2 Map interface.</Description>
</TypeDeclaration>
</TypeDeclarations>
<WorkflowProcesses>
<WorkflowProcess Id="eai" Name="EAI Data Transformation" AccessLevel="PRIVATE">
<ProcessHeader DurationUnit="D">
<Created>2004-08-08T21:28:00+0100</Created>
<Description>
This workflow exemplifies straight-through processing, EAI (Enterprise Application Integration), and
data transformation.
</Description>
</ProcessHeader>
<RedefinableHeader PublicationStatus="UNDER_TEST"/>
<FormalParameters>
<FormalParameter Id="order" Mode="IN">
<DataType>
<DeclaredType Id="WebOrder"/>
</DataType>
</FormalParameter>
</FormalParameters>
<DataFields>
<DataField Id="accountNumber" Name="Account Number">
<DataType>
<BasicType Type="STRING"/>
</DataType>
<Description>The user's internal account number.</Description>
</DataField>
<DataField Id="salesOrder" Name="Sales Order">
<DataType>
<DeclaredType Id="Document"/>
</DataType>
</DataField>
<DataField Id="int">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</DataField>
<DataField Id="bool">
<DataType>
<BasicType Type="BOOLEAN"/>
</DataType>
</DataField>
<DataField Id="date">
<DataType>
<BasicType Type="DATETIME"/>
</DataType>
</DataField>
</DataFields>
<Applications>
<Application Id="lookupAccount" Name="Lookup Account Number">
<Description>Finds the internal Web Store account number for the specified employee.</Description>
<FormalParameters>
<FormalParameter Id="userID" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
<Description>The employee's user ID.</Description>
</FormalParameter>
<FormalParameter Id="accountNumber" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
<Description>The employee's Web Store account number.</Description>
</FormalParameter>
</FormalParameters>
</Application>
<Application Id="obe.transform" Name="Transform XML Document">
<Description>This procedure transforms an XML document using an XSL transform.</Description>
<FormalParameters>
<FormalParameter Id="in" Mode="IN">
<DataType>
<DeclaredType Id="Document"/>
</DataType>
<Description>The input XML document, represented as a W3C DOM node.</Description>
</FormalParameter>
<FormalParameter Id="transformUri" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
<Description>This is the URI of the XSL transform to apply</Description>
</FormalParameter>
<FormalParameter Id="parameters" Mode="IN">
<DataType>
<DeclaredType Id="Map"/>
</DataType>
<Description>A map of input parameters, keyed on name.</Description>
</FormalParameter>
<FormalParameter Id="out" Mode="OUT">
<DataType>
<DeclaredType Id="Document"/>
</DataType>
<Description>The transformed XML document, represented as a W3C DOM node.</Description>
</FormalParameter>
</FormalParameters>
</Application>
<Application Id="submitOrder" Name="Submit Order">
<Description>
Submits a sales order to the Web Service entry point for the Sales Order Handling System.
</Description>
<ExternalReference location="http://localhost:8080/obeexamples/services/SalesOrdersPort?wsdl"
  xref="raiseOrder" namespace="http://www.def.com/2004/pub/sales"/>
</Application>
</Applications>
<Activities>
<Activity Id="lookupAccNum" Name="Lookup Account Number">
<Implementation>
<Tool Id="lookupAccount" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>string($order/defws:web-order/defws:header/defws:userid)</ActualParameter>
<ActualParameter>accountNumber</ActualParameter>
</ActualParameters>
<Description>
Extract the user ID from the inbound document and look up that user's internal account number.
</Description>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="170"/>
<ExtendedAttribute Name="YOffset" Value="50"/>
<ExtendedAttribute Name="obe.Bounds">
<obe:Bounds x="41" y="48" width="140" height="50"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Activity>
<Activity Id="transform" Name="Transform Data">
<Implementation>
<Tool Id="obe.transform" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>$order</ActualParameter>
<ActualParameter>'web-sales-order.xsl'</ActualParameter>
<ActualParameter>def:createMap('account-number', $accountNumber)</ActualParameter>
<ActualParameter>salesOrder</ActualParameter>
</ActualParameters>
<Description>
Transforms the order document from the web store into the format required by the
Sales Order Handling System.
</Description>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="310"/>
<ExtendedAttribute Name="YOffset" Value="50"/>
<ExtendedAttribute Name="obe.Bounds">
<obe:Bounds x="287" y="49" width="140" height="50"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Activity>
<Activity Id="submitOrder" Name="submit Order">
<Implementation>
<Tool Id="submitOrder" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>$salesOrder</ActualParameter>
</ActualParameters>
<Description>
Invokes the Sales Order Processing System's Web Service to submit the order.
</Description>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="440"/>
<ExtendedAttribute Name="YOffset" Value="50"/>
<ExtendedAttribute Name="obe.Bounds">
<obe:Bounds x="544" y="50" width="140" height="50"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Activity>
</Activities>
<Transitions>
<Transition Id="eai_Tra2" From="lookupAccNum" To="transform" Name="Transition">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition Id="eai_Tra3" From="transform" To="submitOrder" Name="Transition">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
</Transitions>
<ExtendedAttributes>
<ExtendedAttribute Name="obe.Event">
<obe:Event Id="DEFWebOrderReceived">
<xpdl:ActualParameters>
<xpdl:ActualParameter>order</xpdl:ActualParameter>
</xpdl:ActualParameters>
</obe:Event>
</ExtendedAttribute>
<ExtendedAttribute Name="StartOfWorkflow" Value="FreeTextExpressionParticipant;lookupAccNum;60;50;NOROUTING"/>
<ExtendedAttribute Name="EndOfWorkflow" Value="FreeTextExpressionParticipant;submitOrder;580;50;NOROUTING"/>
<ExtendedAttribute Name="ParticipantVisualOrder" Value="FreeTextExpressionParticipant;"/>
</ExtendedAttributes>
</WorkflowProcess>
</WorkflowProcesses>
<ExtendedAttributes>
<ExtendedAttribute Name="MadeBy" Value="JaWE"/>
<ExtendedAttribute Name="Version" Value="1.2"/>
</ExtendedAttributes>
</Package>

Solution Files

See the solution files under $OBE_HOME/examples:

Deployment and Execution

The eai workflow supports both manual and triggered start.
1 Mandatory, because the order attribute appears as a <FormalParameter> of the <WorkflowProcess>, meaning that it must be assigned a value before a newly created process instance can be started.