Skip Headers
Oracle® BPEL Process Manager Developer's Guide
10g Release 2 (10.1.2)
B14448-02
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

4 Manipulating XML Data in BPEL

This chapter describes how to manipulate XML data in BPEL, including the large role that XPath expressions play in manipulating XML data.

This chapter contains the following topics:

4.1 Use Cases for Manipulating XML Data in BPEL

This chapter covers a variety of use cases for how you can manipulate XML data in BPEL. The use cases include topics such as how to work with variables, perform tasks such as mathematical calculations, and work with sequences and arrays. This chapter reviews the simplest to the most advanced methods for manipulating XML data in BPEL. The explanations are largely by example, and provide an introduction to the supporting specifications without repeating their details.

Most of the examples in this chapter assume that the WSDL file defining the associated message types is document-literal style rather than the RPC style. There is a difference in how XPath query strings are formed for RPC-style WSDL definitions. If you are working with a type defined in an RPC WSDL file, see "Differences Between Document-Style and RPC-Style WSDL Files".


See Also:

The sample files located at
  • C:\orabpel\samples\tutorials\103.XMLDocuments (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\tutorials\103.XMLDocuments (for JDeveloper BPEL Designer)


4.2 Overview of Manipulating XML Data in BPEL Concepts

This section covers the following topics:

4.2.1 How XML Data Works in BPEL

In a BPEL process, every piece of data is in XML format. This includes the messages passed to and from the BPEL process, the messages exchanged with external services, and local variables used by the flow. You define the types for these messages and variables with the XML schema, usually in the WSDL file for the flow or in the WSDL files for the services it invokes. Therefore, all variables in BPEL are XML data, and any BPEL process uses much of its code to manipulate these XML variables. This typically includes performing data transformation between representations required for different services, and local manipulation of data (for example, to combine the results from several service invocations).

4.2.2 About Data Manipulation and XPath Standards

The starting point for data manipulation in BPEL is the assign activity, which builds on the XPath standard. XPath queries, expressions, and functions play a large part in this type of manipulation. In addition, more advanced methods are available that involve using XQuery, XSLT, or Java, usually to do more complex data transformation or manipulation.

This section provides a general overview of how to manipulate XML data in BPEL. It summarizes the key building blocks used in various combinations and provides examples. The remaining sections in this chapter discuss and illustrate how to apply these building blocks to perform specific tasks.You use the assign activity to copy data from one XML variable to another, or to calculate the value of an expression and store it in a variable. A copy element within the activity specifies the source and target of the assignment (what to copy from and to), which must be of compatible types. The formal syntax as shown in the Business Process Execution Language for Web Services Specification is as follows:

<assign standard-attributes>
   standard-elements
   <copy>+
      from-spec
      to-spec
   </copy>
</assign>

This syntax is described in detail in that specification. The from-spec and to-spec typically specify a variable or variable part, as in:

<assign>
   <copy>
      <from variable="c1" part="address"/
      <to variable="c3"/>
   </copy>
</assign>

Rather than repeating all syntax details, this chapter shows and describes excerpts taken primarily from sample projects provided in the C:\orabpel\samples\references directory for Eclipse BPEL Designer and Oracle_Home\integration\orabpel\samples\references directory for JDeveloper BPEL Designer.


Note:

If you used the tutorials with either BPEL designer (JDeveloper BPEL Designer or Eclipse BPEL Designer) to add an assign activity to the process, you supplied details about the activity in a Copy Rule window that included a From section and a To section. This reflects the underlying BPEL source code syntax shown previously in this section.

XPath standards play a key role in the assign activity. Brief examples are shown here as an introduction; examples with more context and explanation are provided in the sections that follow.

  • XPath queries: An XPath query selects a field within a source or target variable part. The from or to clause can include a query attribute whose value is an XPath query string. For example:

    <from variable="input" part="payload"
          query="/p:CreditFlowRequest/p:ssn">
    
    

    For XPath version 1.0, the value of the query attribute must be an absolute location path that selects exactly one node. You can find further details about the query attribute and XPath standards syntax in the Business Process Execution Language for Web Services Specification (section 14.3) and the XML Path Language (XPath) Specification, respectively.

  • XPath expressions: You use an XPath expression (specified in an expression attribute in the from clause) to indicate a value to be stored in a variable. For example:

    <from expression="100"/>
    
    

    The expression can be any general expression—that is, an XPath expression that evaluates to any XPath value type. For more information about XPath expressions, see section 9.1.4 of the XML Path Language (XPath) Specification.

Within XPath expressions, you can call the following types of functions:

  • Core XPath functions: XPath supports a large number of built-in functions, including functions for string manipulation (such as concat), numeric functions (like sum), and others.

    <from expression="concat('string one', 'string two')"/>
    
    

    For a complete list of the functions built into XPath standards, see section 4 of the XML Path Language (XPath) Specification.

  • BPEL XPath extension functions: BPEL adds several extension functions to the core XPath core functions, enabling XPath expressions to access information from a process. The extensions are defined in the standard BPEL namespace http://schemas.xmlsoap.org/ws/2003/03/business-process/ and indicated by the prefix bpws:

    <from expression= Òbpws:getVariableData('input', 'payload', '/p:value') + 1"/>
    
    

    For more information, see sections 9.1 and 14.1 of the Business Process Execution Language for Web Services Specification.

  • Oracle BPEL Extension XPath functions: Oracle provides some additional XPath functions that use the capabilities built into BPEL and XPath standards for adding new functions.

    These functions are defined in the namespace http://schemas.oracle.com/xpath/extension and indicated by the prefix ora:. If you have Oracle BPEL Process Manager installed locally, Oracle BPEL Console lists and describes all available XPath functions through the following URL:


    See Also:

    The XPath extension documentation available at either of the following locations:

  • Custom functions: You can also create custom XPath functions. If you do, you must register them in the BPEL process deployment descriptor or in the following XML files:

    • C:\orabpel\domains\default\config\xpath-functions.xml file (for Eclipse BPEL Designer)

    • Oracle_Home\integration\orabpel\domains\default\config\xpath-functions.xml file (for JDeveloper BPEL Designer)

    Then, package the source implementing them into a BPEL suitcase or Oracle BPEL Process Manager startup environment. For more information about writing custom XPath functions, refer to: http://www.oracle.com/technology/bpel

Sophisticated data manipulation can be difficult to perform with the BPEL assign activity and the core XPath functions. However, you can perform complex data manipulation and transformation by using XSLT or Java, or as a Web service. For more information on calling Java code from within BPEL, see the tutorial under the BPEL Tutorials link at http://www.oracle.com/technology/bpel. For XSLT, Oracle BPEL Process Manager includes XPath functions that execute these transformations.


See Also:

The following XPath and XQuery transformation code examples:
  • C:\orabpel\samples\tutorials\114.XSLTTransformations (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\tutorials\114.XSLTTransformations (for JDeveloper BPEL Designer)

  • Chapter 14, "XSLT Mapper and Transformations"


The following sections show related definitions in the BPEL and WSDL files that help explain the examples.

4.3 Initializing a Variable with Expression Constants or Literal XML

It is often useful to assign literal XML to a variable in BPEL, for example, to initialize a variable before copying dynamic data into a specific field within the XML data content for the variable. This is also useful for testing purposes when you want to hard code XML data values into the process.

This example assigns a literal result element to the payload part of the output variable:

<assign>
   <!-- copy from literal xml to the variable -->
   <copy>
      <from>
         <result xmlns="http://samples.otn.com">
            <name/>
            <symbol/>
            <price>12.3</price>
            <quantity>0</quantity>
            <approved/>
            <message/>
         </result>
      </from>
      <to variable="output" part="payload"/>   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.4 Copying Between Variables

When you copy between variables, you copy directly from one variable (or part) to another variable of a compatible type, without needing to specify a particular field within either variable. In other words, there is no need to specify an XPath query.The following example performs two assignments, first copying between two variables of the same type and then copying a variable part to another variable with the same type as that part.

<assign>
   <copy>
      <from variable="c1"/>
      <to variable="c2"/>
   </copy>
   <copy>
      <from variable="c1" part = "address"/>
      <to variable="c3"/>
   </copy>
</assign>

The BPEL file defines the variables as follows:

<variable name="c1" messageType="x:person"/>
<variable name="c2" messageType="x:person"/>
<variable name="c3" element="x:address"/>

The WSDL file defines the person message type as follows:

<message name="person" xmlns:x="http://tempuri.org/bpws/example">
   <part name="full-name" type="xsd:string"/>
   <part name="address" element="x:address"/>
</message>

See Also:

Section 9.3.2 of the Business Process Execution Language for Web Services Specification for this code example

4.5 Accessing Fields within Complex Type Variables

Given the types of definitions present in most WSDL files, you must go down to the level of copying from or to a field within part of a complex type variable. To do this, you specify an XPath query in the from or to clause of the assign activity.

This example copies the ssn field from the CreditFlow process's input message into the ssn field of the credit rating service's input message.

<assign>
   <copy>
      <from variable="input" part="payload"
         query="/tns:CreditFlowRequest/tns:ssn"/>
      <to variable="crInput" part="payload" query="/tns:ssn"/>
   </copy>
</assign>

The BPEL file defines the variables involved in this assignment as follows:

<variable name="input" messageType="tns:CreditFlowRequestMessage"/>
<variable name="crInput"
          messageType="services:CreditRatingServiceRequestMessage"/>

The crInput variable is used as an input message to a credit rating service. Its message type, CreditFlowRequestMessage, is defined in CreditFlowService.wsdl as follows:

<message name="CreditFlowRequestMessage">
<part name="payload" element="tns:CreditFlowRequest"/>
</message>

CreditFlowRequest is defined with a field named ssn. The message type CreditRatingServiceRequestMessage is defined in CreditRatingService.wsdl as follows:

<message name="CreditRatingServiceRequestMessage">
   <part name="payload" element="tns:ssn"/>
</message>

See Also:

The following samples:
  • C:\bpelz\workspace\CreditFlow (for Eclipse BPEL Designer)

  • C:\orabpel\samples\utils\CreditRatingService (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\utils\CreditRatingService (for JDeveloper BPEL Designer)


4.6 Assigning Numeric Values

You can assign numeric values in XPath expressions. The following example shows how to assign an XPath expression with the integer value 100.

<assign>
   <!-- copy from integer expression to the variable -->
   <copy>
      <from expression="100"/>
      <to variable="output" part="payload" query="/p:result/p:quantity"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.7 Mathematical Calculations with XPath Standards

You can use simple mathematical expressions like the one in the following example, which increments a numeric value.

In this example, the BPEL XPath function getVariableData retrieves the value being incremented. The arguments to getVariableData are equivalent to the variable, part, and query attributes of the from clause (including the last two arguments, which are optional).

<assign>
   <copy>
      <from expression="bpws:getVariableData('input', 'payload',
          '/p:value') + 1"/>
      <to variable="output" part="payload" query="/p:result"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.8 Assigning String Literals

This example copies an expression evaluating to the string literal 'GE' to the symbol field within the indicated variable part. (Note the use of the double and single quotes.)

<assign>
   <!-- copy from string expression to the variable -->
   <copy>
      <from expression="'GE'"/>
      <to variable="output" part="payload" query="/p:result/p:symbol"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.9 Concatenating Strings

Rather than copy the value of one string variable (or variable part or field) to another, you first can perform string manipulation, such as concatenating several strings together. In Chapter 3, "Building a Simple BPEL Process", you concatenated the string 'Hello ' with a name supplied in an input message. A similar example from the assign reference sample is shown in the following syntax. The concatenation is accomplished with the core XPath function named concat; in addition, the variable value involved in the concatenation is retrieved with the BPEL XPath function getVariableData.

In this example, getVariableData fetches the value of the name field from the input variable's payload part. The string literal 'Hello ' is then concatenated to the beginning of this value.

<assign>
   <!-- copy from XPath expression to the variable -->
   <copy>
      <from expression="concat('Hello ',
         bpws:getVariableData('input', 'payload', '/p:name'))"/>
      <to variable="output" part="payload" query="/p:result/p:message"/>
   </copy>
</assign>

Other string manipulation functions available in XPath are listed in section 4.2 of the XML Path Language (XPath) Specification.


See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.10 Assigning Boolean Values

In this example of assigning Boolean values, the XPath expression in the from clause is a call to XPath's Boolean function true, and the specified approved field is set to true. The function false is also available.

<assign>
   <!-- copy from boolean expression function to the variable -->
   <copy>
      <from expression="true()"/>
      <to variable="output" part="payload" query="/result/approved"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\Assign (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\Assign (for JDeveloper BPEL Designer)


4.11 Assigning Date or Time

You can assign the current value of a date or time field by using the BPEL XPath function getCurrentDate, getCurrentTime, or getCurrentDateTime, respectively. In addition, if you have a date-time value in the standard XSD format, you can convert it to characters more suitable for output by calling the BPEL XPath function formatDate.For related information, see section 9.1.2 of the Business Process Execution Language for Web Services Specification.

<!-- execute the XPath extension function getCurrentDate() -->
<assign>
   <copy>
      <from expression="ora:getCurrentDate()"/>
      <to variable="output" part="payload"
         query="/invoice/invoiceDate"/>
   </copy>
</assign>

In the next example, the formatDate function converts the date-time value provided in XSD format to the string 'Jun 10, 2005' (and assigns it to the string field formattedDate).

<!-- execute the XPath extension function formatDate() -->
<assign>
   <copy>
      <from expression="ora:formatDate('2005-06-10T15:56:00',
         'MMM dd, yyyy')"/>
      <to variable="output" part="payload"
         query="/invoice/formattedDate"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.12 Manipulating Attributes

You may want to copy to or from something defined as an XML attribute. An at sign (@) in XPath query syntax refers to an attribute instead of a child element.

The following code example fetches and copies the custId attribute from this XML data:

   <invalidLoanApplication xmlns="http://samples.otn.com">
      <application xmlns = "http://samples.otn.com/XPath/autoloan">
         <customer custId = "111" >
            <name>
               Mike Olive
            </name>
            ...
         </customer>
         ...
      </application>
   </invalidLoanApplication>

The following example selects the custId attribute of the customer field and assigns it to the variable custId:

<assign>
   <!-- get the custId attribute and assign to variable custId -->
   <copy>
      <from variable="input" part="payload"
         query="/tns:invalidLoanApplication/autoloan:application
                /autoloan:customer/@custId"/>
      <to variable="custId"/>
   </copy>
</assign>

The namespace prefixes in this example are optional and not integral to the example.The WSDL file defines a customer to have a type in which custId is defined as an attribute, as follows:

<complexType name="CustomerProfileType">
   <sequence>
      <element name="name" type="string"/>
      ...
   </sequence>
   <attribute name="custId" type="string"/>
</complexType>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPath (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPath (for JDeveloper BPEL Designer)


4.13 Manipulating XML Data Sequences that Use Arrays

Data sequences are one of the most basic data models used in XML. However, manipulating them can be nontrivial. One of the most common data sequence patterns used in BPEL processes are arrays. Based on the XML schema, the way you can identify a data sequence definition is by its attribute maxOccurs being set to a value of more than one or marked as unbounded. See the XML Schema Specification at http://www.w3.org/TR for more information.

The examples in this section illustrate several basic ways of manipulating data sequences in BPEL. However, there are other associated requirements, such as performing looping or dynamic referencing of endpoints. For additional code samples and further information regarding real-world use cases for data sequence manipulation in BPEL, see http://www.oracle.com/technology/bpel.Each of the following sections describes a particular requirement for data sequence manipulation. For a code example that describes all data sequences, see ArraySample.bpel, which takes a data sequence as input and loops through it, adding together individual line items in each data sequence element into a total value.


See Also:

The ArraySample.bpel sample file located at:
  • C:\orabpel\samples\tutorials\112.Arrays (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\tutorials\112.Arrays (for JDeveloper BPEL Designer)


4.13.1 Statically Indexing into an XML Data Sequence that Uses Arrays

The following two examples illustrate how to use XPath functionality to select a data sequence element when the index of the element you want is known at design time. In these cases, it is the first element.

In the following example, addresses[1] selects the first element of the addresses data sequence:

<assign>
   <!-- get the first address and assign to variable address -->
   <copy>
      <from variable="input" part="payload"
         query="/tns:invalidLoanApplication/autoloan:application
                /autoloan:customer/autoloan:addresses[1]"/>
      <to variable="address"/>
   </copy>
</assign>

In this query, addresses[1] is equivalent to addresses[position()=1], where position is one of the core XPath functions (see sections 2.4 and 4.1 of the XML Path Language (XPath) Specification). The query in the next example calls the position function explicitly to select the first element of the addresses data sequence. It then selects that address's street element (which the activity assigns to the variable street1).

<assign>
   <!-- get the first address's street and assign to street1 -->
   <copy>
      <from variable="input" part="payload"
         query="/tns:invalidLoanApplication/autoloan:application
                /autoloan:customer/autoloan:addresses[position()=1]
                /autoloan:street"/>
      <to variable="street1"/>
   </copy>
</assign>

If you review the definition of the input variable and its payload part in the WSDL file, you go several levels down before coming to the definition of the addresses field. There you see the maxOccurs="unbounded" attribute. The two XPath indexing methods are functionally identical; you can use whichever method you prefer.


See Also:

The following samples:
  • C:\orabpel\samples\references\XPath (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPath (for JDeveloper BPEL Designer)


4.13.2 Determining Sequence Size

If you need to know the run-time size of a data sequence—that is, the number of nodes or data items in the sequence—you can get it by using the combination of the XPath built-in count() function and the BPEL built-in getVariableData() function.

This example calculates the number of elements in the item sequence and assigns it to the integer variable lineItemSize:

<assign>
   <copy>
      <from expression="count(bpws:getVariableData('outpoint', 'payload',
                        '/p:invoice/p:lineItems/p:item')"/>
      <to variable="lineItemSize"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.13.3 Dynamically Indexing by Applying a Trailing XPath to an Expression

Often a dynamic value is needed to index into a data sequence—that is, you need to get the nth node out of a sequence, where the value of n is defined at run time. This section covers the following methods for dynamically indexing by applying a trailing XPath into expressions:

4.13.3.1 Dynamic Indexing Example

The dynamic indexing method shown here applies a trailing XPath to the result of bwps:getVariableData(), instead of using an XPath as the last argument of bpws:getVariableData(). The trailing XPath references to an integer-based index variable within the position predicate (that is, [...]):

<variable name="idx" type="xsd:integer"/>
...
<assign>
  <copy>
    <from expression="bpws:getVariableData('input','payload'
       )/p:line-item[bpws:getVariableData('idx')]/p:line-total" />
    <to variable="lineTotalVar" />
  </copy>
</assign> 

Assume at run time that the idx integer variable holds 2 as its value. The preceding expression within the from is equivalent to:

<from expression="bpws:getVariableData('input','payload'
       )/p:line-item[2]/p:line-total" />

There are some subtle XPath usage differences, when an XPath used trailing behind the bwps:getVariableData() function is compared with the one used inside the function.Using the same example (where payload is the message part of element "p:invoice"), if the XPath is used within the getVariableData() function, the root element name ("/p:invoice") must be specified at the beginning of the XPath.

For example:

bpws:getVariableData('input', 'payload','/p:invoice/p:line-item[2]/p:line-total')

If the XPath is used trailing behind the bwps:getVariableData()function, the root element name does not need to be specified in the XPath.

For example:

bpws:getVariableData('input', 'payload')/p:line-item[2]/p:line-total

This is because the node returned by the getVariableData() function is already the root element. Specifying the root element name again in the XPath is redundant and is standard XPath semantics.

4.13.3.2 Using the bpel:append Extension to Append New Items to a Sequence

The bpelx:append extension under assign enables BPEL processes to append new elements to an existing parent element:

    <assign name="assign-3">
        <copy>
            <from expression="bpws:getVariableData('idx')+1" />
            <to variable="idx"/>
        </copy>
        <bpelx:append>
            <bpelx:from variable="partInfoResultVar" part="payload" />
            <bpelx:to variable="output" part="payload" />
        </bpelx:append>
        ...
    </assign>

The bpelx:append logic in this example appends the payload element of the partInfoResultVar variable as a child to the payload element of the output variable. In others words, the payload element of output variable is used as the parent element.


See Also:

The following samples:
  • "Assign Activity" for details about using multiple copies of this extension in a single assign activity

  • C:\orabpel\samples\tutorials\126.DataAggregator\AggregationTutorial (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\tutorials\126.DataAggregator\AggregationTutorial (for JDeveloper BPEL Designer)


4.13.3.3 Merging Data Sequences

You can merge two sequences into a single data sequence. This pattern is common when the data sequences are in an array (that is, the sequence of data items of compatible types).The following two append operations under assign demonstrate how to merge data sequences:

<assign>
    <!-- initialize "mergedLineItems" variable
         to an empty element -->
    <copy>
        <from> <p:lineItems /> </from>
        <to variable="mergedLineItems" />
    </copy>
    <bpelx:append>
          <bpelx:from variable="input" part="payload"
                query="/p:invoice/p:lineItems/p:lineitem" />
          <bpelx:to variable="mergedLineItems" />
    </bpelx:append>
    <bpelx:append>
          <bpelx:from variable="literalLineItems"
                query="/p:lineItems/p:lineitem" />
          <bpelx:to variable="mergedLineItems" />
    </bpelx:append>
</assign> 

See Also:

The ArraySample.bpel sample file located at:
  • C:\orabpel\samples\tutorials\112.Arrays (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\tutorials\112.Arrays (for JDeveloper BPEL Designer)


4.13.3.4 Dynamically Indexing with the BPEL getElement Function

If you do not want to use the two-step process of creating an XPath query to dynamically index into a sequence, you can use the XPath function getElement instead. This function takes a sequence and an index (which can be a dynamic value, such as a variable) and returns the appropriate sequence element.

<variable name="lineItemIndex" type="xsd:int"/>
...
<!-- execute the XPath extension function getElement(arrayOfElements[],
index) to fetch one element from an array of elements
-->
<assign>
   <copy>
      <from expression="ora:getElement('output', 'payload',
         '/invoice/lineItems/item',
         bpws:getVariableData('lineItemIndex'))"/>
      <to variable="myLineItem"/>   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.13.3.5 Merging Data Sequences that Use Arrays

You can merge two sequences of compatible types into a single sequence. To do so, use the XPath function mergeChildNodes.

<!-- execute the XPath extension function mergeChildNodes(e1, e2) and assign to a variable -->
<assign>
   <copy>
      <from expression="ora:mergeChildNodes(
         bpws:getVariableData('input', 'payload', '/invoice/lineItems'),
         bpws:getVariableData('literalLineItems'))"/>
      <to variable="mergedLineItems"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.13.3.6 Appending New Items to a Sequence that Uses an Array

The BPEL XPath function addChildNode enables BPEL processes to append new elements to an existing sequence.

<!-- execute the XPath extension function addChildNode(Element e, Node childNode)
-->
<assign>
   <copy>      <from expression="ora:addChildNode(bpws:getVariableData('output',
         'payload', '/invoice/lineItems'),
          bpws:getVariableData('escapedLineItem'))"/>
      <to variable="output" part="payload" query="/invoice/lineItems"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.13.4 SOAP-Encoded Arrays Not Supported

Oracle BPEL Process Manager does not support SOAP-encoded arrays (soapenc:arrayType).

Use one of the following workarounds:

  • Apache Axis supports document-literal style services. This means you can change the service to not use soapenc:arrayType.

  • A wrapper can be placed around the service (also using Apache Axis) so that the BPEL process talks to the document literal wrapper service, which in turn calls the underlying service with soapenc:arrayType.

  • Call a service with soapenc:arrayType from BPEL, but construct the XML message more manually in the BPEL code. This enables you to avoid changing or wrapping the service. However, each time you want to call that service from BPEL, you must take extra steps.

4.14 Converting from a String to an XML Element

Sometimes a service is defined to return a string, but the content of the string is actually XML data. The problem is that, although BPEL provides support for manipulating XML data (using XPath queries, expressions, and so on), this functionality is not available if the variable or field is of type string. With Java, you use document object model (DOM) functions to convert the string to a structured XML object type. You can use the BPEL XPath function parseEscapedXML to do the same thing. This function takes XML data, parses it through DOM, and returns structured XML data that can be assigned to a typed BPEL variable. For example:

<!-- execute the XPath extension functionparseEscapedXML('&lt;item&gt;') and assign to a variable
-->
<assign>
   <copy>
      <from expression="ora:parseEscapedXML(
         '&lt;item xmlns=&quot;http://samples.otn.com&quot;
                   sku=&quot;006&quot;&gt;
          &lt;description&gt;sun ultra sparc VI server
          &lt;/description&gt;
          &lt;price&gt;1000
          &lt;/price&gt;
          &lt;quantity&gt;2
          &lt;/quantity&gt;
          &lt;lineTotal&gt;2000
          &lt;/lineTotal&gt;
          &lt;/item&gt;')"/>
      <to variable="escapedLineItem"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\references\XPathFunction (for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\references\XPathFunction (for JDeveloper BPEL Designer)


4.15 Differences Between Document-Style and RPC-Style WSDL Files

The examples shown up to this point have been for document-style WSDL files, in which a message is defined with an XML schema element, as in the following example:

<message name="LoanFlowRequestMessage">
<part name="payload" element="s1:loanApplication"/>
</message>

This is in contrast to RPC-style WSDL files, in which the message is defined with an XML schema type, as in:

<message name="LoanFlowRequestMessage">
<part name="payload" type="s1:LoanApplicationType"/>
</message>

This affects the material in this chapter because there is a difference in how XPath queries are constructed for the two WSDL message styles. For an RPC-style message, the top-level element (and therefore the first node in an XPath query string) is the part name (payload in the previous example). In document-style, the top-level node is the element name (for example, loanApplication).The following example shows what an XPath query string looks like if the LoanServices used in BPEL demo applications (such as LoanFlow) were RPC style.

RPC-Style WSDL File

<message name="LoanServiceResultMessage">
   <part name="payload" type="s1:LoanOfferType"/>
</message>

<complexType name="LoanOfferType">
   <sequence>
      <element name="providerName" type="string"/>
      <element name="selected" type="boolean"/>
      <element name="approved" type="boolean"/>
      <element name="APR" type="double"/>
   </sequence>
</complexType>

RPC-Style BPEL File

<variable name="output"
          messageType="tns:LoanServiceResultMessage"/>
...
<assign>
   <copy>
      <from expression="9.9"/>
      <to variable="output" part="payload" query="/payload/APR"/>
   </copy>
</assign>

See Also:

The following samples:
  • C:\orabpel\samples\utils\AsyncLoanService (LoanServices for Eclipse BPEL Designer)

  • C:\orabpel\samples\demos\LoanDemo\LoanFlow (BPEL demo application for Eclipse BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\utils\AsyncLoanService (LoanServices for JDeveloper BPEL Designer)

  • Oracle_Home\integration\orabpel\samples\demos\LoanDemo\LoanFlow (BPEL demo application for JDeveloper BPEL Designer)


4.15.1 Enclosing the Operation Name with RPC-Style WSDL Messages

If you use RPC-style messaging, you must enclose the input XML message with an operation name (in the following example, process):

<process xmlns="http://xmlns.oracle.com/MessageParts_referingToComplexTypes"> 
<payload xmlns="" 
xmlns:client="http://xmlns.oracle.com/MessageParts_referingToComplexTypes"   
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
xsi:type="client:TestInput"> 
  <input
 xmlns="http://xmlns.oracle.com/MessagePartsreferingToComplexTypes">yoo</input 
> 
  <input1 
xmlns="http://xmlns.oracle.com/MessageParts_referingToComplexTypes">boo</input 
1> 
  <input2 
xmlns="http://xmlns.oracle.com/MessageParts_referingToComplexTypes">woo</input 
2> 
  <input3 
xmlns="http://xmlns.oracle.com/MessageParts_referingToComplexTypes">foo</input 
3> 
  <input4 
xmlns="http://xmlns.oracle.com/MessageParts_referingToComplexTypes">goo</input 
4> 
</payload> 
</process> 

If you want to verify the correctness of the XML file, set the validateXML property to true in the Manage BPEL Domain window of Oracle BPEL Console.

4.16 Using Binary Attachments in SOAP Messages

There are two supported methods for transferring opaque data in a SOAP call:

4.16.1 Use Case: SOAP Message with Binary Attachment Using MIME

This section provides a use case and describes design implementation issues. You cannot currently model a SOAP message with an attachment through either BPEL designer (JDeveloper BPEL Designer or Eclipse BPEL Designer). You must manually edit the necessary BPEL and WSDL files.

In this use case:

  • The BPEL process acts as a service to receive and reply to a SOAP message with an attachment.

  • The BPEL process acts as a client to send and receive a response to a SOAP message with an attachment.

  • Binary data is assigned to another variable.

  • Binary data is read from a URL.

  • Binary data is saved to a local file.

Two BPEL processes are constructed:

  • MIMEService is essentially an echo service of a SOAP message with an attachment. This process does the following:

    • Receives a SOAP message with an attachment and saves the opaque data to a local file.

    • Assigns the opaque data to an output variable.

    • Uses the output variable to reply to a SOAP message with an attachment to the invoker.

  • MIMERequester is the client of the first service. This process does the following:

    • Reads the binary data from a URL and assigns it to a variable.

    • Uses the variable as input to perform an invoke on the first process.

    • Receives a SOAP message with an attachment.

4.16.1.1 WSDL File Contents

The following WSDL file defines MIMEService. This file uses the WSDL binding MIME extension to define the SOAP message with an attachment.

<?xml version="1.0" encoding="UTF-8"?>
<definitions
. . .
. . .
   <types>
   . . .
   . . .
      <schema xmlns="http://www.w3.org/2001/XMLSchema">
          <import namespace="http://schemas.xmlsoap.org/ws/2003/03/addressing"
          schemaLocation="http://gmi-pc:9700/orabpel/xmllib/ws-addressing.xsd" /> 
      </schema>
   </types>

   <message name="ReplyToHeader">
      <part name="ReplyTo" element="wsa:ReplyTo" /> 
   </message>
   <message name="MessageIDHeader">
      <part name="MessageID" element="wsa:MessageID" /> 
   </message>
   <message name="RelatesToHeader">
      <part name="RelatesTo" element="wsa:RelatesTo" /> 
   </message>
   <message name="MIMEServiceRequestMessage">
      <part name="payload" type="xsd:int"/>
      <part name="bin" type="xsd:anyType"/>
   </message>   
<message name="MIMEServiceResponseMessage">
      <part name="payload" type="xsd:int"/>
      <part name="bin" type="xsd:anyType"/>
   </message>

    <portType name="MIMEService">
        <operation name="initiate">
           <input message="tns:MIMEServiceRequestMessage"/>
        </operation>
        <operation name="process">
           <input message="tns:MIMEServiceRequestMessage"/>
           <output message="tns:MIMEServiceResponseMessage"/>
        </operation>
    </portType>
    <portType name="MIMEServiceCallback">
        <operation name="onResult">
           <input message="tns:MIMEServiceResponseMessage"/>
        </operation>
    </portType>

    <binding name="MIMEServiceBinding" type="tns:MIMEService">
        <soap:binding style="rpc"
 transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="initiate">
            <soap:operation style="rpc" soapAction="initiate"/>
            <input>
                <mime:multipartRelated>
                    <mime:part>
                       <soap:header message="tns:MessageIDHeader"
                          part="MessageID" use="literal"/> 
                       <soap:header message="tns:ReplyToHeader"
                          part="ReplyTo" use="literal"/> 
                       <soap:body parts="payload" use="literal"/>
                    </mime:part>
                    <mime:part>
                       <mime:content part="bin" type="binary"/>
                    </mime:part>
                </mime:multipartRelated>
            </input>
        </operation>
        <operation name="process">
            <soap:operation style="rpc" soapAction="process"/>
            <input>
                <mime:multipartRelated>
                    <mime:part>
                       <soap:header message="tns:RelatesToHeader"
                          part="RelatesTo" use="literal"/> 
                       <soap:body parts="payload" use="literal"/>
                    </mime:part>
                    <mime:part>
                       <mime:content part="bin" type="binary"/>
                    </mime:part>
                </mime:multipartRelated>
            </input>
            <output>
                <mime:multipartRelated>
                    <mime:part>
                        <soap:body parts="payload" use="literal"/>
                    </mime:part>
                    <mime:part>
                        <mime:content part="bin" type="binary"/>
                    </mime:part>
                </mime:multipartRelated>
            </output>
        </operation>
     </binding>
     <binding name="MIMEServiceCallbackBinding" type="tns:MIMEServiceCallback">
        <soap:binding style="rpc"
 transport="http://schemas.xmlsoap.org/soap/http"/> 
           <operation name="onResult">
        <soap:operation style="rpc" soapAction="onResult"/>
           <input>
           <mime:multipartRelated>
              <mime:part>
                 <soap:header message="tns:RelatesToHeader"
              part="RelatesTo" use="literal"/> 
                 <soap:body use="literal" /> 
              </mime:part>
              <mime:part>
                <mime:content part="bin" type="binary"/>
              </mime:part>
           </mime:multipartRelated>
          </input>
        </operation>
    </binding>

  <plnk:partnerLinkType name="MIMEService">
     <plnk:role name="MIMEServiceProvider">
       <plnk:portType name="tns:MIMEService"/>
     </plnk:role>
     <plnk:role name="MIMEServiceRequester">
       <plnk:portType name="tns:MIMEServiceCallback"/>
     </plnk:role>
  </plnk:partnerLinkType>
</definitions>

In this WSDL, the schema type of the binary data is xsd:anyType. This is because xsd:binary was deprecated from XSD version 2000 to version 2001. (Web Services Description Language (WSDL) Specification 1.1 has an example using xsd:binary. This has become an outstanding issue.)

To ensure that payload validation is successful, use xsd:anyType with either MIME or DIME.

4.16.1.2 BPEL File Contents

The MIMERequester.bpel file shows how to use binary data in BPEL:

<process . . .
. . .
. . .
 <sequence>
    <!-- receive input from requestor -->
    <receive name="receiveInput" partnerLink="client"
             portType="tns:MIMERequester"
             operation="initiate" variable="input"
             createInstance="yes"/>
             
    <!-- initialize the input of MIMEService -->
    <assign>
      <copy>
        <from variable="input" part="payload" query="/tns:value"/>
        <to variable="request" part="payload" query="/payload"/>
      </copy>
      <copy>
        <from expression="ora:readBinaryFromFile('request.bin')"/>
        <to variable="request" part="bin"/>
      </copy>
 </assign>
 <invoke name="invoke" partnerLink="MIMEService"
            portType="services:MIMEService"
            operation="initiate" inputVariable="request"/>
            
    <receive name="receive" partnerLink="MIMEService"
            portType="services:MIMEServiceCallback"
            operation="onResult" variable="response"/>
    <assign>
      <copy>
        <from variable="response" part="payload" query="/payload"/>
        <to variable="request" part="payload" query="/payload"/>
      </copy>
      <copy>
        <from expression="ora:writeBinaryToFile('response', 'bin',
 'C:/Temp/response.bin')"/>
        <to variable="response" part="bin"/>
      </copy>
      <copy>
          <from expression="ora:readBinaryFromFile('request2.bin')"/>
        <to variable="request" part="bin"/>
      </copy>
    </assign>     <invoke name="invoke" partnerLink="MIMEService"
            portType="services:MIMEService"
            operation="process" inputVariable="request"
            outputVariable="response"/>  
 <assign>
      <copy>
        <from variable="response" part="payload" query="/payload"/>
        <to variable="output" part="payload" query="/tns:result"/>
      </copy>
      <copy>
        <from expression="ora:writeBinaryToFile('response', 'bin',
 'C:/Temp/response2.bin')"/>
        <to variable="response" part="bin"/>
      </copy>
    </assign>        <!-- respond output to requestor -->
    <invoke name="replyOutput" partnerLink="client"
            portType="tns:MIMERequesterCallback"
            operation="onResult" inputVariable="output"/>        
  </sequence>
</process>

In this example, XPath extension function ora:readBinaryFromFile( ) reads the binary file and ora:writeBinaryToFile( ) writes the binary content to a file.

The binary data can be assigned to another variable like a normal XML document by using the standard BPEL assign activity. The BPEL assign activity is extended here to accommodate the binary data.

4.16.1.3 Java Client Using SAAJ

MIMEService can be accessed from a Java client. There are two access options:

  • Java API for XML-Based RPC (JAX-RPC)

  • SOAP with Attachments API Java (SAAJ)

Example 4-1 uses Axis' implementation of SAAJ to invoke MIMEService. This example is used to unit test the interoperability of the created service. The sample request sent by this example is shown in Example 4-2.

Example 4-1 SAAJ Example

public boolean initiateUsingSAAJ(String filename) throws Exception {
 String endPointURLString =  "http://localhost:" +opts.getPort() +
 "/orabpel/default/MIMEService/1.0";

   SOAPConnectionFactory soapConnectionFactory =
        javax.xml.soap.SOAPConnectionFactory.newInstance();
   SOAPConnection soapConnection =
        soapConnectionFactory.createConnection();
        
   MessageFactory messageFactory =
        MessageFactory.newInstance();
   SOAPMessage soapMessage =
        messageFactory.createMessage();
   MimeHeaders hd = soapMessage.getMimeHeaders();
   hd.addHeader("SOAPAction", "initiate");

   SOAPPart soapPart = soapMessage.getSOAPPart();
   SOAPEnvelope requestEnvelope =
        soapPart.getEnvelope();
   SOAPBody body = requestEnvelope.getBody();
   SOAPBodyElement operation = body.addBodyElement
        (requestEnvelope.createName("initiate"));

   Vector dataHandlersToAdd = new Vector();
   dataHandlersToAdd.add(new DataHandler(new FileDataSource(new
         File(filename))));

   javax.xml.soap.SOAPElement element1 =
         operation.addChildElement(requestEnvelope.createName("payload"));
         element1.addTextNode("1");
        
   if (dataHandlersToAdd != null) {
       ListIterator dataHandlerIterator =
             dataHandlersToAdd.listIterator();

       while (dataHandlerIterator.hasNext()) {
              DataHandler dataHandler = (DataHandler)
                    dataHandlerIterator.next();
              javax.xml.soap.SOAPElement element =
                    operation.addChildElement(requestEnvelope.createName("bin"));
              javax.xml.soap.AttachmentPart attachment =
                    soapMessage.createAttachmentPart(dataHandler);
              soapMessage.addAttachmentPart(attachment);
              element.addAttribute(requestEnvelope.createName
                       ("href"), "cid:" + attachment.getContentId());
                       }
             }
   javax.xml.soap.SOAPMessage returnedSOAPMessage =
       soapConnection.call(soapMessage, endPointURLString);
   if (returnedSOAPMessage == null)
      return true;
   Iterator iterator = returnedSOAPMessage.getAttachments();
   if (!iterator.hasNext()) {
      //The wrong type of object that what was expected.
      System.out.println("Received problem response from server");
      throw new AxisFault("", "Received problem response from server", null,
        null);

     }
     //Still here, so far so good.
     //Now lets brute force compare the source attachment
     // to the one we received.

     DataHandler rdh = (DataHandler)
        ((AttachmentPart)iterator.next()).getDataHandler();

     //From here we'll just treat the data resource as file.
     String receivedfileName = rdh.getName();//Get the filename. 

     if (receivedfileName == null) {
        System.err.println("Could not get the file name.");
        throw new AxisFault("", "Could not get the file name.", null, null);
     }

     System.out.println("Going to compare the files..");
     boolean retv = compareFiles(filename, receivedfileName);

     java.io.File receivedFile = new java.io.File(receivedfileName);
     receivedFile.delete();

     return retv;
   }
}

Example 4-2 shows the sample request sent by the SAAJ program:

Example 4-2 Sample Request

POST /orabpel/default/MIMEService/1.0 HTTP/1.0Content-Type: multipart/related;
 type="text/xml"; start="<F090DFD56421FD84AAF98C386AD50A44>"; boundary="----=_
Part_0_27211574.1133404205718"Accept: application/soap+xml, application/dime,
 multipart/related, text/*User-Agent: Axis/1.2.1Host: gmi-pc:1234Cache-Control:
 no-cachePragma: no-cacheSOAPAction: "initiate"Content-Length: 9307------=_Part_0_
27211574.1133404205718Content-Type: text/xml;
 charset=UTF-8Content-Transfer-Encoding: binaryContent-Id:
 <F090DFD56421FD84AAF98C386AD50A44><?xml version="1.0"
 encoding="UTF-8"?><soapenv:Envelope
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><initiate
 xmlns=""><payload xmlns="">1</payload><bin
 href="cid:1A744998BA8527BD121CAE96C022109F"
 xmlns=""/></initiate></soapenv:Body></soapenv:Envelope>------=_Part_0_
27211574.1133404205718Content-Type:
 application/octet-streamContent-Transfer-Encoding: binaryContent-Id:
 <1A744998BA8527BD121CAE96C022109F>
.....................


See Also:

The following documentation:

4.17 Summary

This chapter provides an overview of the role of XML data in BPEL processes, including describing the large role that XPath expressions play in manipulating XML data.