6 Manipulating XML Data in a BPEL Process

This chapter describes how to manipulate XML data in a BPEL process service component. This chapter provides a variety of examples. Topics include how to work with variables, sequences, and arrays, how to use XPath expressions, and how to perform tasks such as mathematical calculations. The explanations are largely by example, and provide an introduction to the supported specifications.

This chapter includes the following sections:

Note:

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 Section 6.18, "Understanding the Differences Between Document-Style and RPC-Style WSDL Files."

6.1 Introduction to Manipulating XML Data in BPEL Processes

This section provides an introduction to using XML data in BPEL processes.

6.1.1 XML Data in BPEL

In a BPEL process service component, most pieces of data are in XML format. This includes the messages passed to and from the BPEL process service component, the messages exchanged with external services, and local variables used by the process. You define the types for these messages and variables with the XML schema, usually in the Web Services Description Language (WSDL) file for the flow, the WSDL files for the services it invokes, or the XSD file referenced by those WSDL files. Therefore, most variables in BPEL are XML data, and any BPEL process service component 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).

BPEL also supports service data object (SDO) variables, which are not in an XML format, but rather in a memory structure format.

6.1.2 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. Example 6-1 shows the formal syntax, as described in the Business Process Execution Language for Web Services Specification:

Example 6-1 Assign Activity

<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 shown in Example 6-2:

Example 6-2 from-spec and to-spec Attributes

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

When you use Oracle JDeveloper, you supply assign activity details in a Copy Operation dialog that includes a From section and a To section. This reflects the preceding BPEL source code syntax.

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. Example 6-3 provides an example:

    Example 6-3 query Attribute

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

    The value of the query attribute must be a 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). Similarly, the value of an expression attribute must return exactly one node or one object only when it is used in the from clause within a copy operation. 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 XPath extension 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:.

  • Custom functions

    Oracle BPEL Process Manager functions are defined in the bpel-xpath-functions-config.xml and placed inside the orabpel.jar file. For more information, see Section B.7, "Creating User-Defined XPath Extension Functions" and Oracle Fusion Middleware Administrator's Guide for Oracle SOA Suite.

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, Java, or a bpelx operation under an assign activity (See Section 6.14, "Manipulating XML Data with bpelx Extensions"), or as a web service. For XSLT, Oracle BPEL Process Manager includes XPath functions that execute these transformations.

For more information about XPath and XQuery transformation code examples, see Chapter 35, "Creating Transformations with the XSLT Mapper."

Note:

Passing large schemas through an assign activity can cause Oracle JDeveloper to freeze up and run low on memory if you right-click the payload in the From or To section of the Copy Operation dialog and select Expand All. As a workaround, manually expand the payload elements.

6.2 Delegating XML Data Operations to Data Provider Services

You can specify BPEL data operations to be performed by an underlying data provider service through use of the entity variable. The data provider service performs the data operations in a data store behind the scenes and without use of other data store-related features provided by Oracle SOA Suite (for example, the database adapter). This action enhances Oracle SOA Suite runtime performance and incorporates native features of the underlying data provider service during compilation and runtime.

For this release, the entity variable can be used with an Oracle Application Development Framework (ADF) Business Component data provider service using SDO-based data.

In previous releases, variables and messages exchanged within a BPEL business process were disconnected payload (a snapshot of data returned by a web service) placed into an XML structure. In some cases, the user required this type of fit. In other cases, this fit presented challenges.

The entity variable addresses the following challenges of previous releases:

  • Extensive data conversion

    If the underlying data was not in XML form, data conversion (for example, translating delimited text to XML) was required. If the underlying size of the data was large, the processing potentially impacted performance.

  • Stale snapshot data

    Variables (including WSDL messages) in BPEL processes were disconnected payload. In some cases, this was required. In other cases, you wanted a variable to represent the most recent data being modified by other applications outside Oracle BPEL Process Manager. This meant the disconnected data model provided a stale data set that did not fit all needs. The snapshot also duplicated data, which impacted performance when the data size was large.

  • Loss of native data behavior

    Some data conversion implementation required data structure enforcement or business data logic beyond the XML schema. For example, the start date needed to be smaller than the end date. When the variable was a disconnected payload, validation occurred only during related web service invocation. Optionally performing the extra business data logic after certain operations, but before web service invocation, was sometimes preferred.

To address these challenges with this release, you create an entity variable during variable declaration. An entity variable acts as a data handle to access and plug in different data provider service technologies behind the scenes. During compilation and runtime, Oracle BPEL Process Manager delegates data operations to the underlying data provider service.

Table 6-1 provides an example of how data conversion was performed in previous releases (using the database adapter as an example) and in release 11g with the entity variable.

Table 6-1 Data Manipulation Capabilities in Previous and Current Releases

10.1.x Releases 11g Release When Using the Entity Variable

Data operations such as explicitly loading and saving data were performed by the database adapter in Oracle BPEL Process Manager. All data (for example, of a purchase order) was saved in the database dehydration store.

Data operations such as loading and saving data are performed automatically by the data provider service (the Oracle ADF Business Component application), without asking you to code any service invocation.

Oracle BPEL Process Manager stores a key (for example, purchase order ID (POID)) that points to this data. Oracle BPEL Process Manager fetches the key when access to data is requested (the bind entity activity does this). You must explicitly request the data to be bound using the key. Any data changes are persisted by the data provider service in a database that can be different from the dehydration store database. This prevents data duplication.

Data in variables was in document object model (DOM) form

Data in variables is in SDO form, which provides for a simpler conversion process than DOM, especially when the data provider service understands SDO forms.


Note:

Only BPEL process service components currently allow the use of SDO-formed variables. If your composite application has an Oracle Mediator service component wired with an SDO-based Java binding component reference, the data form of the variable defaults to DOM. In addition, the features described for 10.1.x releases in Table 6-1 are still supported in release 11g.

The following documentation describes use of the entity variable:

  • bpel-203-EntityVariableToADFBC:

    This sample uses an entity variable bound to an Oracle ADF BC service using an SDO interface. This provides the BPEL process with a variable that behaves like a standard BPEL variable. However, the data is maintained outside the BPEL process (in this case, in an Oracle ADF BC component). Rather than passing around a large payload of data, it resides in one place. A reference key is passed around to read and update the data.

  • bpel-204-EntityVariableToBPELBackedSDO:

    This sample shows how you can use the Oracle ADF BC SDO interface, but with a back-end implementation other than an Oracle ADF BC application. In this case, the back end is implemented using a BPEL process.

    Visit the following URL for details about these samples:

    http://www.oracle.com/technology/sample_code/products/bpel
    
  • WebLogic Fusion Order Demo application of the Fusion Order Demo

6.2.1 How to Create an Entity Variable

This section describes how to create an entity variable and a binding key in Oracle JDeveloper.

In previous releases of Oracle BPEL Process Manager, all variable data was in DOM form. With release 11g, variable data in SDO form is also supported. DOM and SDO variables in BPEL process service components are implicitly converted to the required forms. For example, an Oracle BPEL process service component using DOM-based variables can automatically convert these variables as required to SDO-based variables in an assign activity, and vice versa. Both form types are defined in the XSD schema file. No user intervention is required.

Entity variables also support SDO-formed data. However, unlike the DOM and SDO variables, the entity variable with SDO-based data enables you to bind a unique key value to data (for example, a purchase order). Only the key is stored in the dehydration store; the data requiring conversion is stored with the service of the Oracle ADF Business Component application. The key points to the data stored in the service. When the data is required, it is fetched from the data provider service and placed into memory. The process occurs in two places: the bind entity activity and the dehydration store. For example, when Oracle BPEL Process Manager rehydrates, it stores only the key for the entity variable; when it wakes up, it does an implicit bind to get the current data.

6.2.1.1 Understanding How SDO Works in the Inbound Direction

The SDO binding component service provides the outside world with an entry point to the composite application, as shown in Figure 6-1.

Figure 6-1 Inbound Direction

Description of Figure 6-1 follows
Description of "Figure 6-1 Inbound Direction"

You use the SOA Composite Editor and Oracle BPEL Designer to perform the following tasks:

  • Define an SDO binding component service and a BPEL process service component in the composite application.

  • Connect (wire) the SDO service and BPEL process service component.

  • Define the details of the BPEL process service component.

For more information about using the SOA Composite Editor, see Chapter 2, "Developing SOA Composite Applications with Oracle SOA Suite."

6.2.1.2 Understanding How SDO Works in the Outbound Direction

The SDO binding component reference enables messages to be sent from the composite application to Oracle ADF Business Component application external partners in the outside world, as shown in Figure 6-2.

Figure 6-2 Outbound Direction

Description of Figure 6-2 follows
Description of "Figure 6-2 Outbound Direction"

When the Oracle ADF Business Component application is the external partner link to the outside world, there is no SDO binding component reference in the SOA Composite Editor that you drag into the composite application to create outbound communication. Instead, communication between the composite application and the Oracle ADF Business Component application occurs as follows:

  • The Oracle ADF Business Component application is deployed and automatically registered as an SDO service in the Service Infrastructure

  • Oracle JDeveloper is used to browse for and discover this application as an ADF-BC service and create a partner link connection.

  • The composite.xml file is automatically updated with reference details (the binding.adf property) when the Oracle ADF Business Component application service is discovered.

6.2.1.3 Creating an Entity Variable and Choosing a Partner Link

You now create an entity variable and select a partner link for the Oracle ADF Business Component application. The following example describes how the OrderProcessor BPEL process service component receives an ID for an order by using a bind entity activity to point to order data in an Oracle ADF Business Component data provider service in the WebLogic Fusion Order Demo application.

To create an entity variable and choose a partner link:

  1. Go to the Structure window of the BPEL process service component in Oracle JDeveloper.

  2. Right-click the Variables folder and select Expand All Child Nodes.

  3. In the second Variables folder, right-click and select Create Variable.

    The Create Variable dialog appears.

  4. In the Name field, enter a name.

  5. Click the Entity Variable checkbox and select the Search icon to the right of the Partner Link field.

    The Partner Link Chooser dialog appears with a list of available services, including the SDO service called ADF-BC Service.

  6. Browse for and select the service for the Oracle ADF Business Component application.

  7. Click OK to close the Partner Link Chooser and Create Variable dialogs.

    The Create Variable dialog looks as shown in .

    Figure 6-3 Create Variable Dialog

    Description of Figure 6-3 follows
    Description of "Figure 6-3 Create Variable Dialog"

6.2.1.4 Creating a Binding Key

You now create a key to point to the order data in the Oracle ADF Business Component data provider service.

To create a binding key:

  1. Drag a Bind Entity activity into your BPEL process service component.

    The Bind Entity dialog appears.

  2. In the Name field, enter a name.

  3. To the right of the Entity Variable field, click the Search icon.

    The Variable Chooser dialog appears.

  4. Select the entity variable created in Section 6.2.1.3, "Creating an Entity Variable and Choosing a Partner Link" and click OK.

  5. In the Unique Keys section, click the Add icon.

    The Specify Key dialog appears. You use this dialog to create a key for retrieving the order ID from the Oracle ADF Business Component data provider service.

  6. Enter the details described in Table 6-2 to define the binding key:

    Table 6-2 Specify Key Dialog Fields and Values

    Field Value

    Key Local Part

    Enter the local part of the key.

    Key Namespace URI

    Enter the namespace URI for the key.

    Key Value

    Enter the key value expression. This expression must match the type of a key. The following examples show expression value keys for a POID key:

    • $inputMsg.payload/tns:poid

    • bpws:getVariableData('inputmsg','payload','tns:poid')

    The POID key for an entity variable typically comes from another message. If the type of POID key is an integer and the expression result is a string of ABC, the string-to-integer fails and the bind entity activity also fails at runtime.


    Figure 6-4 shows the Specify Key dialog after completion.

    Figure 6-4 Specify Key Dialog

    Description of Figure 6-4 follows
    Description of "Figure 6-4 Specify Key Dialog"

  7. Click OK to close the Specify Key dialog.

    A name-pair value appears in the Unique Keys table, as shown in . Design is now complete.

    Figure 6-5 Bind Entity Dialog

    Description of Figure 6-5 follows
    Description of "Figure 6-5 Bind Entity Dialog"

  8. Click OK to close the Bind Entity dialog.

    After the Bind Entity activity is executed at runtime, the entity variable is ready to be used.

For more information about using SDOs, see Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework. This guide describes how to expose application modules as web services and publish rows of view data objects as SDOs. The application module is the ADF framework component that encapsulates business logic as a set of related business functions.

6.3 Using Standalone SDO-based Variables

Standalone SDO-based variables are similar to ordinary BPEL XML-DOM-based variables. The major difference is that the underlying data form is SDO-based, instead of DOM-based. Therefore, SDO-based variables can use some SDO features such as Java API access, an easier-to-use update API, and the change summary. However, SDO usage is also subject to some restrictions that do not exist with XML-DOM-based variables. The most noticeable restriction is that SDO only supports a small subset of XPath expressions.

6.3.1 How to Declare SDO-based Variables

The syntax for declaring an SDO-based variable is similar to that for declaring BPEL variables. Example 6-4 provides details.

Example 6-4 SDO-based Variable Declaration

<variable name="deptVar_s" element="hrtypes:dept" />
<variable name="deptVar_v" element="hrtypes:dept" bpelx:sdoCapable="false" />

If you want to override the automatic detection, use the bpelx:sdoCapable="true|false" switch. For example, variable deptVar_v described in Example 6-4 is a regular DOM-based variable. Example 6-4 provides an example of the schema.

Example 6-5 XSD Sample

<xsd:element name="dept" type="Dept"/>
   <xsd:complexType name="Dept"
    sdoJava:instanceClass="sdo.sample.service.types.Dept">
      <xsd:annotation>
         <xsd:appinfo source="Key"
          xmlns="http://xmlns.oracle.com/bc4j/service/metadata/">
            <key>
               <attribute>Deptno</attribute>
            </key>
            <fetchMode>minimal</fetchMode>
         </xsd:appinfo>
      </xsd:annotation>
      <xsd:sequence>
         <xsd:element name="Deptno" type="xsd:integer" minOccurs="0"/>
         <xsd:element name="Dname" type="xsd:string" minOccurs="0"
 nillable="true"/>
         <xsd:element name="Loc" type="xsd:string" minOccurs="0" nillable="true"/>
         <xsd:element name="Emp" type="Emp" minOccurs="0" maxOccurs="unbounded"
 nillable="true"/>
      </xsd:sequence>
   </xsd:complexType>

6.3.2 How to Convert from XML to SDO

Oracle BPEL Process Manager supports dual data forms: DOM and SDO. You can interchange the usage of DOM-based and SDO-based variables within the same business process, even within the same expression. The Oracle BPEL Process Manager data framework automatically converts back and forth between DOM and SDO forms.

By using the entity variable XPath rewrite capabilities, Oracle BPEL Process Manager enables some XPath features (for example, variable reference and function calls) that the basic SDO specification does not support. However, there are other limitations on the XPath used with SDO-based variables (for example, there is no support for and, or, and not).

Example 6-6 provides a simple example of converting from XML to SDO.

Example 6-6 XML-to-SDO Conversion

<assign>
        <copy>
            <from>
   <ns0:dept xmlns:ns0="http://sdo.sample.service/types/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ns0:Deptno>10</ns0:Deptno>
      <ns0:Dname>ACCOUNTING</ns0:Dname>
      <ns0:Loc>NEW YORK</ns0:Loc>
      <ns0:Emp>
         <ns0:Empno>7782</ns0:Empno>
         <ns0:Ename>CLARK</ns0:Ename>
         <ns0:Job>MANAGER</ns0:Job>
         <ns0:Mgr>7839</ns0:Mgr>
         <ns0:Hiredate>1981-06-09</ns0:Hiredate>
         <ns0:Sal>2450</ns0:Sal>
         <ns0:Deptno>10</ns0:Deptno>
      </ns0:Emp>
      <ns0:Emp>
         <ns0:Empno>7839</ns0:Empno>
         <ns0:Ename>KING</ns0:Ename>
         <ns0:Job>PRESIDENT</ns0:Job>
         <ns0:Hiredate>1981-11-17</ns0:Hiredate>
         <ns0:Sal>5000</ns0:Sal>
         <ns0:Deptno>10</ns0:Deptno>
      </ns0:Emp>
      <ns0:Emp>
         <ns0:Empno>7934</ns0:Empno>
         <ns0:Ename>MILLER</ns0:Ename>
         <ns0:Job>CLERK</ns0:Job>
         <ns0:Mgr>7782</ns0:Mgr>
         <ns0:Hiredate>1982-01-23</ns0:Hiredate>
         <ns0:Sal>1300</ns0:Sal>
         <ns0:Deptno>10</ns0:Deptno>
      </ns0:Emp>
   </ns0:dept>
            </from>
            <to variable="deptVar_s" />
        </copy>
</assign>

Example 6-7 provides an example of copying from an XPath expression of an SDO variable to a DOM variable.

Example 6-7 Copy from an XPath Expression of an SDO Variable to a DOM Variable

<assign>
        <!-- copy from an XPath expression of an SDO variable to DOM variable -->
        <copy>
            <from expression="$deptVar_s/hrtypes:Emp[2]" />
            <to variable="empVar_v" />
        </copy>
        <!-- copy from an XPath expression of an DOM variable to SDO variable -->
        <copy>
            <from expression="$deptVar_v/hrtypes:Emp[2]" />
            <to variable="empVar_s" />
        </copy>
        <!-- insert a DOM based data into an SDO variable -->
        <bpelx:insertAfter>
            <bpelx:from variable="empVar_v" />
            <bpelx:to variable="deptVar_s" query="hrtypes:Emp" />
        </bpelx:insertAfter>
        <!-- insert a SDO based data into an SDO variable at particular location,
              no XML conversion is needed  -->
        <bpelx:insertBefore>
            <bpelx:from expression="$deptVar_s/hrtypes:Emp[hrtypes:Sal = 1300]" />
            <bpelx:to variable="deptVar_s" query="hrtypes:Emp[6]" />
         </bpelx:insertBefore>
</assign>

Example 6-8 provides an example of removing a portion of SDO data.

Example 6-8 SDO Data Removal

<assign>
         <bpelx:remove>
            <bpelx:target variable="deptVar_s" query="hrtypes:Emp[2]" />
        </bpelx:remove>
</assign>

Note:

The bpelx:append operation is not supported for SDO-based variables for the following reasons:
  • The <copy> operation on an SDO-based variable has smart update capabilities (for example, you do not have to perform a <bpelx:append> before the <copy> operation).

  • The SDO data object is metadata driven and does not generally support adding a new property arbitrarily.

6.4 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.

6.4.1 How To Assign a Literal XML Element

Example 6-9 assigns a literal result element to the payload part of the output variable:

Example 6-9 Literal Element Assignment

<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>

6.5 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, you do not need to specify an XPath query.

6.5.1 How to Copy Between Variables

Example 6-10 shows two assignments being performed, 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.

Example 6-10 Copying Between Variables

<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 shown in Example 6-11:

Example 6-11 Variable Definition

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

The WSDL file defines the person message type shown in Example 6-12:

Example 6-12 Message Type Definition

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

For more information about this code example, see Section 9.3.2 of the Business Process Execution Language for Web Services Specification.

6.6 Accessing Fields Within Element-Based and Message Type-Based Variables

Given the types of definitions present in most WSDL and XSD files, you must go down to the level of copying from or to a field within part of a variable based on the element and message type. This in turn uses XML schema complex types. To perform this action, you specify an XPath query in the from or to clause of the assign activity.

6.6.1 How to Access Fields Within Element-Based and Message Type-Based Variables

In Example 6-13, the ssn field is copied from the CreditFlow process's input message into the ssn field of the credit rating service's input message.

Example 6-13 Field Copying Levels

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

Example 6-14 shows how the BPEL file defines message type-based variables involved in this assignment:

Example 6-14 BPEL File Definition - Message Type-Based Variables

<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 the CreditFlowService.wsdl file, as shown in Example 6-15:

Example 6-15 CreditFlowRequestMessage Definition

<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 the CreditRatingService.wsdl file, as shown in Example 6-16:

Example 6-16 CreditRatingServiceRequestMessage Definition

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

A BPEL process can also use element-based variables. In Example 6-17, the autoloan field is copied from the loan application process's input message into the customer field of a web service's input message.

Example 6-17 Field Copying Levels

 <assign>  
      <copy>
        <from variable="input" part="payload" 
           query="/tns:invalidLoanApplication/autoloan:
            application/autoloan:customer"/>
        <to variable="customer"/>
      </copy>
</assign>

Example 6-18 shows how the BPEL file defines element-based variables involved in an assignment:

Example 6-18 BPEL File Definition - Element-Based Variables

    <variable name="customer" element="tns:customerProfile"/>

6.7 Assigning Numeric Values

You can assign numeric values in XPath expressions.

6.7.1 How to Assign Numeric Values

Example 6-19 shows how to assign an XPath expression with the integer value of 100.

Example 6-19 XPath Expression Assignment

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

6.8 Using Mathematical Calculations with XPath Standards

You can use simple mathematical expressions like the one in Section 6.8.1, "How To Use Mathematical Calculations with XPath Standards," which increment a numeric value.

6.8.1 How To Use Mathematical Calculations with XPath Standards

In Example 6-20, 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).

Example 6-20 XPath Function getVariableData Retrieval of a Value

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

You can also use $variable syntax, as shown in Example 6-21:

Example 6-21 $variable Syntax Use

<assign>
  <copy>
    <from expression="$input.payload + 1"/>
    <to variable="output" part="payload" query="/p:result"/>
  </copy>
</assign>

6.9 Assigning String Literals

You can assign string literals to a variable in BPEL.

6.9.1 How to Assign String Literals

The code in Example 6-22 copies an expression evaluating from the string literal 'GE' to the symbol field within the indicated variable part. (Note the use of the double and single quotes.)

Example 6-22 Expression Copy

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

6.10 Concatenating Strings

Rather than copying the value of one string variable (or variable part or field) to another, you can first perform string manipulation, such as concatenating several strings.

6.10.1 How to Concatenate Strings

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 Example 6-23, 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.

Example 6-23 XPath Function getVariableData Fetch of Data

<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.

6.11 Assigning Boolean Values

You can assign boolean values with the XPath boolean function.

6.11.1 How to Assign Boolean Values

Example 6-24 provides an 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.

Example 6-24 Boolean Value Assignment

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

The XPath specification recommends that you use the "true()" and "false()" functions as a method for returning boolean constant values.

If you instead use "boolean(true)" or "boolean(false)", the true or false inside the boolean function is interpreted as a relative element step, and not as any true or false constant. It attempts to select a child node named true under the current XPath context node. In most cases, the true node does not exist. Therefore, an empty result node set is returned and the boolean() function in XPath 1.0 converts an empty node set into a false result. This result can be potentially confusing.

6.12 Assigning a Date or Time

You can assign the current value of a date or time field by using the Oracle 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 Oracle BPEL XPath function formatDate.

For related information, see section 9.1.2 of the Business Process Execution Language for Web Services Specification.

6.12.1 How to Assign a Date or Time

Example 6-25 shows an example that uses the function getCurrentDate.

Example 6-25 Date or Time Assignment

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

In Example 6-26, 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).

Example 6-26 formatDate Function

<!-- 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>

6.13 Manipulating Attributes

You can 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.

6.13.1 How to Manipulate Attributes

The code in Example 6-27 fetches and copies the custId attribute from this XML data:

Example 6-27 custId Attribute Fetch and Copy Operations

   <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 code in Example 6-28 selects the custId attribute of the customer field and assigns it to the variable custId:

Example 6-28 custId Attribute Select and Assign Operations

<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 not integral to the example.The WSDL file defines a customer to have a type in which custId is defined as an attribute, as shown in Example 6-29:

Example 6-29 custId Attribute Definition

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

6.14 Manipulating XML Data with bpelx Extensions

You can perform various operations on XML data in assign activities. The bpelx extension types described in this section provide this functionality.

6.14.1 How to Use bpelx:append

Note:

The bpelx:append extension is not supported with SDO variables and causes an error.

The bpelx:append extension in an assign activity enables a BPEL process service component to append the contents of one variable, expression, or XML fragment to another variable's contents. Example 6-30 provides an example.

Example 6-30 bpelx:append Extension

<bpel:assign> 
   <bpelx:append>
      <bpelx:from ... /> 
      <bpelx:to ... /> 
   </bpelx:append> 
</bpel:assign> 

The from-spec query within bpelx:append yields zero or more nodes. The node list is appended as child nodes to the target node specified by the to-spec query.

The to-spec query must yield one single L-Value element node. Otherwise, a bpel:selectionFailure fault is generated. The to-spec query cannot refer to a partner link.

Example 6-31 consolidates multiple bills of material into one single bill of material (BOM) by appending multiple b:parts for one BOM to b:parts of the consolidated BOM.

Example 6-31 Consolidation of Multiple Bills of Material

<bpel:assign>
    <bpelx:append>
          <from variable="billOfMaterialVar" 
                query="/b:bom/b:parts/b:part" />
          <to variable="consolidatedBillOfMaterialVar"
                query="/b:bom/b:parts" />
    </bpelx:append> 
</bpel:assign>

6.14.2 How to Use bpelx:insertBefore

Note:

The bpelx:insertBefore extension works with SDO variables, but the target must be the variable attribute into which the copied data must go.

The bpelx:insertBefore extension in an assign activity enables a BPEL process service component to insert the contents of one variable, expression, or XML fragment before another variable's contents. Example 6-32 provides an example.

Example 6-32 bpelx:insertBefore Extension

<bpel:assign> 
   <bpelx:insertBefore>
      <bpelx:from ... /> 
      <bpelx:to ... /> 
   </bpelx:insertBefore> 
</bpel:assign>

The from-spec query within bpelx:insertBefore yields zero or more nodes. The node list is appended as child nodes to the target node specified by the to-spec query.

The to-spec query of the insertBefore operation points to one or more single L-Value nodes. If multiple nodes are returned, the first node is used as the reference node. The reference node must be an element node. The parent of the reference node must also be an element node. Otherwise, a bpel:selectionFailure fault is generated. The node list generated by the from-spec query selection is inserted before the reference node. The to-spec query cannot refer to a partner link.

Example 6-33 shows the syntax before the execution of <insertBefore>. The value of addrVar is:

Example 6-33 Presyntax Execution

<a:usAddress>
       <a:state>CA</a:state>
       <a:zipcode>94065</a:zipcode> 
</a:usAddress> 

Example 6-34 shows the syntax after the execution:

Example 6-34 Postsyntax Execution

<bpel:assign>
    <bpelx:insertBefore>
        <bpelx:from>
             <a:city>Redwood Shore></a:city>
        </bpelx:from> 
        <bpelx:to "addrVar" query="/a:usAddress/a:state" /> 
    </bpelx:insertBefore> 
</bpel:assign> 

Example 6-35 shows the value of addrVar:

Example 6-35 addrVar Value

<a:usAddress>
       <a:city>Redwood Shore</a:city>
       <a:state>CA</a:state>
       <a:zipcode>94065</a:zipcode> 
</a:usAddress> 

6.14.3 How to Use bpelx:insertAfter

Note:

The bpelx:insertAfter extension works with SDO variables, but the target must be the variable attribute into which the copied data must go.

The bpelx:insertAfter extension in an assign activity enables a BPEL process service component to insert the contents of one variable, expression, or XML fragment after another variable's contents. Example 6-36 provides an example.

Example 6-36 bpelx:insertAfter Extension

<bpel:assign> 
    <bpelx:insertAfter>
       <bpelx:from ... /> 
       <bpelx:to ... /> 
    </bpelx:insertAfter> 
</bpel:assign>

This operation is similar to the functionality described for Section 6.14.2, "How to Use bpelx:insertBefore," except for the following:

  • If multiple L-Value nodes are returned by the to-spec query, the last node is used as the reference node.

  • Instead of inserting nodes before the reference node, the source nodes are inserted after the reference node.

This operation can also be considered a macro of conditional-switch + (append or insertBefore).

Example 6-37 shows the syntax before the execution of <insertAfter>. The value of addrVar is:

Example 6-37 Presyntax Execution

<a:usAddress>
       <a:addressLine>500 Oracle Parkway</a:addressLine> 
       <a:state>CA</a:state>
       <a:zipcode>94065</a:zipcode> 
</a:usAddress>

Example 6-38 shows the syntax after the execution:

Example 6-38 Postsyntax Execution

<bpel:assign>
    <bpelx:insertAfter>
        <bpelx:from>
             <a:addressLine>Mailstop 1op6</a:addressLine>
        </bpelx:from> 
        <bpelx:to "addrVar" query="/a:usAddress/a:addressLine[1]" /> 
    </bpelx:insertAfter> 
</bpel:assign> 

Example 6-39 shows the value of addrVar:

Example 6-39 addrVar Value

<a:usAddress>
       <a:addressLine>500 Oracle Parkway</a:addressLine> 
       <a:addressLine>Mailstop 1op6</a:addressLine>
       <a:state>CA</a:state>
       <a:zipcode>94065</a:zipcode> 
</a:usAddress>

The from-spec query within bpelx:insertAfter yields zero or more nodes. The node list is appended as child nodes to the target node specified by the to-spec query.

6.14.4 How to Use bpelx:remove

The bpelx:remove extension in an assign activity enables a BPEL process service component to remove a variable. Example 6-40 provides an example.

Example 6-40 bpelx:remove Extension

<bpel:assign> 
    <bpelx:remove>
       <bpelx:target variable="ncname" part="ncname"? query="xpath_str" />
    </bpelx:append> 
</bpel:assign>

Node removal specified by the XPath expression is supported. Nodes specified by the XPath expression can be multiple, but must be L-Values. Nodes being removed from this parent can be text nodes, attribute nodes, and element nodes.

The XPath expression can return one or more nodes. If the XPath expression returns zero nodes, then a bpel:selectionFailure fault is generated.

The syntax of bpelx:target is similar to and a subset of to-spec for the copy operation.

Example 6-41 shows addrVar with the following value:

Example 6-41 addrVar

<a:usAddress>
       <a:addressLine>500 Oracle Parkway</a:addressLine> 
       <a:addressLine>Mailstop 1op6</a:addressLine>
       <a:state>CA</a:state>
       <a:zipcode>94065</a:zipcode> 
</a:usAddress>

After executing the syntax shown in Example 6-42 in the BPEL process service component file, the second address line of Mailstop is removed:

Example 6-42 Removal of Second Address Line

<bpel:assign>
    <bpelx:remove>
        <target variable="addrVar" 
            query="/a:usAddress/a:addressLine[2]" />
    </bpelx:remove> 
</bpel:assign> 

After executing the syntax shown in Example 6-43 in the BPEL process service component file, both address lines are removed:

Example 6-43 Removal of Both Address Lines

<bpel:assign>
    <bpelx:remove>
        <target variable="addrVar" 
            query="/a:usAddress/a:addressLine" />
    </bpelx:remove> 
</bpel:assign>

6.14.5 How to Use bpelx:rename and XSD Type Casting

The bpelx:rename extension in an assign activity enables a BPEL process service component to rename an element through use of XSD type casting. Example 6-44 provides an example.

Example 6-44 bpelx:rename Extension

<bpel:assign>
    <bpelx:rename elementTo="QName1"? typeCastTo="QName2"?>
       <bpelx:target variable="ncname" part="ncname"? query="xpath_str" />
    </bpelx:rename> 
</bpel:assign>

The syntax of bpelx:target is similar to and a subset of to-spec for the copy operation. The target must return a list of one more element nodes. Otherwise, a bpel:selectionFailure fault is generated. The element nodes specified in the from-spec are renamed to the QName specified by the elementTo attribute. The xsi:type attribute is added to those element nodes to cast those elements to the QName type specified by the typeCastTo attribute.

Assume you have the employee list shown in Example 6-45:

Example 6-45 xsi:type Attribute

<e:empList>
    <e:emp>
        <e:firstName>John</e:firstName><e:lastName>Dole</e:lastName>
    <e:emp>
    <e:emp xsi:type="e:ManagerType">
        <e:firstName>Jane</e:firstName><e:lastName>Dole</e:lastName>
        <e:approvalLimit>3000</e:approvalLimit>
        <e:managing /> 
    <e:emp>
    <e:emp>
        <e:firstName>Peter</e:firstName><e:lastName>Smith</e:lastName>
    <e:emp>
    <e:emp>
        <e:firstName>Mary</e:firstName><e:lastName>Smith</e:lastName>
    <e:emp>
</e:empList>

Promotion changes are now applied to Peter Smith in the employee list in Example 6-46:

Example 6-46 Application of Promotion Changes

<bpel:assign>
    <bpelx:rename typeCastTo="e:ManagerType">
       <bpelx:target variable="empListVar" 
            query="/e:empList/e:emp[./e:firstName='Peter' and
 ./e:lastName='Smith'" />
    </bpelx:rename> 
</bpel:assign>

After executing the above casting (renaming), the data looks as shown in Example 6-47 with xsi:type info added to Peter Smith:

Example 6-47 Data Output

<e:empList>
    <e:emp>
        <e:firstName>John</e:firstName><e:lastName>Dole</e:lastName>
    <e:emp>
    <e:emp xsi:type="e:ManagerType">
        <e:firstName>Jane</e:firstName><e:lastName>Dole</e:lastName>
        <e:approvalLimit>3000</e:approvalLimit>
        <e:managing /> 
    <e:emp>
    <e:emp xsi:type="e:ManagerType">
        <e:firstName>Peter</e:firstName><e:lastName>Smith</e:lastName>
    <e:emp>
    <e:emp>
        <e:firstName>Mary</e:firstName><e:lastName>Smith</e:lastName>
    <e:emp>
</e:empList>

The employee data of Peter Smith is now invalid, because <approvalLimit> and <managing> are missing. Therefore, <append> is used to add that information. Example 6-48 provides an example.

Example 6-48 Use of append Extension to Add Information

<bpel:assign>
    <bpelx:rename typeCastTo="e:ManagerType">
       <bpelx:target variable="empListVar" 
            query="/e:empList/e:emp[./e:firstName='Peter' and
 ./e:lastName='Smith'" />
    </bpelx:rename> 
    <bpelx:append>
       <bpelx:from>
          <e:approvalLimit>2500</e:approvalLimit>
          <e:managing /> 
       </bpelx:from>
       <bpelx:to variable="empListVar" 
            query="/e:empList/e:emp[./e:firstName='Peter' and
 ./e:lastName='Smith'" />
    </bpelx:append> 
</bpel:assign>

With the execution of both rename and append, the corresponding data looks as shown in Example 6-49:

Example 6-49 rename and append Execution

<e:emp xsi:type="e:ManagerType">
     <e:firstName>Peter</e:firstName><e:lastName>Smith</e:lastName>
     <e:approvalLimit>2500</e:approvalLimit>
     <e:managing /> 
<e:emp>

6.14.6 How to Use bpelx:copyList

The bpelx:copyList extension in an assign activity enables a BPEL process service component to perform a copyList operation of the contents of one variable, expression, or XML fragment to another variable. Example 6-50 provides an example.

Example 6-50 bpelx:copyList Extension

<bpel:assign> 
    <bpelx:copyList>
       <bpelx:from ... />
       <bpelx:to ... /> 
    </bpelx:copyList>
</bpel:assign>

The from-spec query can yield a list of either all attribute nodes or all element nodes. The to-spec query can yield a list of L-value nodes: either all attribute nodes or all element nodes.

All the element nodes returned by the to-spec query must have the same parent element. If the to-spec query returns a list of element nodes, all element nodes must be contiguous.

If the from-spec query returns attribute nodes, then the to-spec query must return attribute nodes. Likewise, if the from-spec query returns element nodes, then the to-spec query must return element nodes. Otherwise, a bpws:mismatchedAssignmentFailure fault is thrown.

The from-spec query can return zero nodes, while the to-spec query must return at least one node. If the from-spec query returns zero nodes, the effect of the copyList operation is similar to the remove operation.

The copylist operation provides the following features:

  • Removes all the nodes pointed to by the to-spec query.

  • If the to-spec query returns a list of element nodes and there are leftover child nodes after removal of those nodes, the nodes returned by the from-spec query are inserted before the next sibling of the last element specified by the to-spec query. If there are no leftover child nodes, an append operation is performed.

  • If the to-spec query returns a list of attribute nodes, those attributes are removed from the parent element. The attributes returned by the from-spec query are then appended to the parent element.

For example, assume a schema is defined as shown in Example 6-51.

Example 6-51 Schema

<schema attributeFormDefault="unqualified"
        elementFormDefault="qualified"
        targetNamespace="http://xmlns.oracle.com/Event_jws/Event/EventTest"
        xmlns="http://www.w3.org/2001/XMLSchema">
        <element name="process">
                <complexType>
                        <sequence>
                                <element name="payload" type="string"
                                  maxOccurs="unbounded"/>
                        </sequence>
                </complexType>
        </element>
        <element name="processResponse">
                <complexType>
                        <sequence>
                                <element name="payload" type="string"
                                   maxOccurs="unbounded"/>
                        </sequence>
                </complexType>
        </element>
</schema> 

The from variable contains the content shown in Example 6-52.

Example 6-52 Variable Content

<ns1:process xmlns:ns1="http://xmlns.oracle.com/Event_jws/Event/EventTest">
            <ns1: payload >a</ns1: payload >
            <ns1: payload >b</ns1: payload >
</ns1:process> 

The to variable contains the content shown in Example 6-53.

Example 6-53 Variable Content

<ns1:processResponse xmlns:ns1="http://xmlns.oracle.com/Event_
 jws/Event/EventTest">
            <ns1: payload >c</ns1: payload >
</ns1:process>

The bpelx:copyList operation looks as shown in Example 6-54.

Example 6-54 bpelx:copyList

<assign>
      <bpelx:copyList>
        <bpelx:from variable="inputVariable" part="payload"
              query="/client:process/client:payload"/>
        <bpelx:to variable="outputVariable" part="payload"
            query="/client:processResponse/client:payload"/>
      </bpelx:copyList>
</assign>

This makes the to variable as shown in Example 6-55.

Example 6-55 Variable Content

<ns1:processResponse xmlns:ns1="http://xmlns.oracle.com/Event_
 jws/Event/EventTest">
            <ns1: payload >a</ns1: payload >
            <ns1: payload >b</ns1: payload >
</ns1:process> 

6.15 Validating XML Data with bpelx:validate

The bpelx:validate function enables you to verify code and identify invalid XML data.

6.15.1 How to Validate XML Data with bpelx:validate

Use this extension as follows:

  • With the validate attribute in an assign activity:

    <assign bpelx:validate="yes|no">
    ... 
    </assign>
    
  • In <bpelx:validate> as a standalone, extended activity that can be used without an assign activity:

    <bpelx:validate variables="NCNAMES" />
    

    For example:

    <bpelx:validate variables="myMsgVariable myPOElemVar" />
    

6.16 Manipulating XML Data Sequences That Resemble 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 process service components 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 greater 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/sample_code/products/bpel. The following sections describe a particular requirement for data sequence manipulation.

6.16.1 How to Statically Index 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 Example 6-56, addresses[1] selects the first element of the addresses data sequence:

Example 6-56 Data Sequence Element Selection

<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 Example 6-57 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).

Example 6-57 position Function Use

<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.

6.16.2 How to Determine Sequence Size

If you must know the runtime 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.

The code in Example 6-58 calculates the number of elements in the item sequence and assigns it to the integer variable lineItemSize.

Example 6-58 Sequence Size Determination

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

6.16.3 How to Dynamically Index by Applying a Trailing XPath to an Expression

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

6.16.3.1 Applying a Trailing XPath to the Result of getVariableData

The dynamic indexing method shown in Example 6-59 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, [...]).

Example 6-59 Dynamic Indexing

<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 runtime 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 the root element. Specifying the root element name again in the XPath is redundant and is incorrect according to standard XPath semantics.

6.16.3.2 Using the bpelx:append Extension to Append New Items to a Sequence

The bpelx:append extension in an assign activity enables BPEL process service components to append new elements to an existing parent element. Example 6-60 provides an example.

Example 6-60 bpelx:append Extension

    <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 other words, the payload element of output variable is used as the parent element.

6.16.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 two append operations shown in Example 6-61 under assign demonstrate how to merge data sequences:

Example 6-61 Data Sequences Merges with append Operations

<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>

6.16.3.4 Generating Functionality Equivalent to an Array of an Empty Element

The genEmptyElem function generates functionality equivalent to an array of an empty element to an XML structure. This function takes the following arguments:

genEmptyElem('ElemQName',int?, 'TypeQName'?, boolean?)

Note the following issues:

  • The first argument specifies the QName of the empty elements.

  • The optional second integer argument specifies the number of empty elements. If missing, the default size is 1.

  • The third optional argument specifies the QName, which is the xsi:type of the generated empty name. This xsi:type pattern matches the SOAPENC:Array. If it is missing or is an empty string, the xsi:type attribute is not generated.

  • The fourth optional boolean argument specifies whether the generated empty elements are XSI - nil, provided the element is XSD-nillable. The default value is false. If missing or false, xsi:nil is not generated.

Example 6-62 shows an append statement initializing a purchase order (PO) document with 10 empty <lineItem> elements under po:

Example 6-62 append Statement

<bpelx:assign> 
    <bpelx:append>
        <bpelx:from expression="ora:genEmptyElem('p:lineItem',10)" />
        <bpelx:to variable="poVar" query="/p:po" /> 
    </bpelx:append>
</bpelx:assign>

The genEmptyElem function in this example can be replaced with an embedded XQuery expression:

ora:genEmptyElem('p:lineItem',10) 
== for $i in (1 to 10) return <p:lineItem />

The empty elements generated by this function are typically invalid XML data. You perform further data initialization after the empty elements are created. Using the same example above, you can perform the following:

  • Add attribute and child elements to those empty lineItem elements.

  • Perform copy operations to replace the empty elements. For example, copy from a web service result to an individual entry in this equivalent array under a flowN activity.

6.16.4 What You May Need to Know About SOAP-Encoded Arrays

Oracle BPEL Process Manager provides limited support for Simple Object Access Protocol (SOAP)-encoded arrays (soapenc:arrayType).

Consider one of the following methodologies to deal with SOAP arrays:

  • Place a wrapper around the service so that the BPEL process service component 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 action 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.

6.16.5 What You May Need to Know About Using the Array Identifier

For processing in Native Format Builder array identifier environments, information is required about the parent node of a node. Because the reportSAXEvents API is used, this information is typically not available for outbound message scenarios. Setting nxsd:useArrayIdentifiers to true in the native schema enables DOM-parsing to be used for outbound message scenarios. Use this setting cautiously, as it can lead to slower performance for very large payloads.

<?xml version="1.0" ?> 

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            xmlns:nxsd="http://xmlns.oracle.com/pcbpel/nxsd" 
            targetNamespace="http://xmlns.oracle.com/pcbpel/demoSchema/csv" 
            xmlns:tns="http://xmlns.oracle.com/pcbpel/demoSchema/csv" 
            elementFormDefault="qualified" 
            attributeFormDefault="unqualified" nxsd:encoding="US-ASCII"   
nxsd:stream="chars" nxsd:version="NXSD" nxsd:useArrayIdentifiers="true"> 
  <xsd:element name="Root-Element"> 
  .... 
  </xsd:element> 
</xsd:schema> 

6.17 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 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.

6.17.1 How To Convert from a String to an XML Element

The parseEscapedXML function takes XML data, parses it through DOM, and returns structured XML data that can be assigned to a typed BPEL variable. Example 6-63 provides an example:

Example 6-63 String to XML Element Conversion

<!-- execute the XPath extension function
parseEscapedXML('&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>

6.18 Understanding the 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 shown in Example 6-64:

Example 6-64 XML Schema element Definition

<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 shown in Example 6-65:

Example 6-65 RPC-Style type Definition

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

6.18.1 How To Use RPC-Style Files

This impacts 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 Example 6-65). In document-style, the top-level node is the element name (for example, loanApplication).

Example 6-66 and Example 6-67 show what an XPath query string looks like if an application named LoanServices were in RPC style.

Example 6-66 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>

Example 6-67 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>

6.19 Manipulating SOAP Headers in BPEL

BPEL's communication activities (invoke, receive, reply, and onMessage) receive and send messages through specified message variables. These default activities permit one variable to operate in each direction. For example, the invoke activity has inputVariable and outputVariable attributes. You can specify one variable for each of the two attributes. This is enough if the particular operation involved uses only one payload message in each direction.

However, WSDL supports multiple messages in an operation. In the case of SOAP, multiple messages can be sent along the main payload message as SOAP headers. However, BPEL's default communication activities cannot accommodate the additional header messages.

Oracle BPEL Process Manager solves this problem by extending the default BPEL communication activities with the bpelx:headerVariable extension. The extension syntax is as shown in Example 6-68:

Example 6-68 bpelx:headerVariable Extension

<invoke bpelx:inputHeaderVariable="inHeader1 inHeader2 ..."
  bpelx:outputHeaderVariable="outHeader1 outHeader2 ..."
  .../>

<receive bpelx:headerVariable="inHeader1 inHeader2 ..." .../>
<onMessage bpelx:headerVariable="inHeader1 inHeader2 ..." .../>
<reply bpelx:headerVariable="inHeader1 inHeader2 ..." .../>

6.19.1 How to Receive SOAP Headers in BPEL

This section provides an example of how to create BPEL and WSDL files to receive SOAP headers.

To receive SOAP headers in BPEL:

  1. Create a WSDL file that declares header messages and the SOAP binding that binds them to the SOAP request. Example 6-69 provides an example.

    Example 6-69 WSDL File Contents

      <!-- custom header -->
      <message name="CustomHeaderMessage">
        <part name="header1" element="tns:header1"/>
        <part name="header2" element="tns:header2"/>
      </message>
    
      <binding name="HeaderServiceBinding" type="tns:HeaderService">
        <soap:binding style="document"
          transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="initiate">
          <soap:operation style="document" soapAction="initiate"/>
            <input>
              <soap:header message="tns:CustomHeaderMessage"
                part="header1" use="literal"/>
              <soap:header message="tns:CustomHeaderMessage"
                part="header2" use="literal"/>
              <soap:body use="literal"/>
            </input>
        </operation>
      </binding>
    
  2. Create a BPEL source file that declares the header message variables and uses bpelx:headerVariable to receive the headers, as shown in Example 6-70.

    Example 6-70 bpelx:headerVariable Use

    <variables>  <variable name="input"
                 messageType="tns:HeaderServiceRequestMessage"/>
      <variable name="event"
                 messageType="tns:HeaderServiceEventMessage"/>
      <variable name="output"
                 messageType="tns:HeaderServiceResultMessage"/>
      <variable name="customHeader"
                 messageType="tns:CustomHeaderMessage"/>
    </variables>
    
    <sequence>
      <!-- receive input from requester -->
      <receive name="receiveInput" partnerLink="client" 
        portType="tns:HeaderService" operation="initiate" 
        variable="input"
        bpelx:headerVariable="customHeader"
     createInstance="yes"/>
    

6.19.2 How to Send SOAP Headers in BPEL

This section provides an example of how to send SOAP headers.

To send SOAP headers in BPEL:

  1. Define an SCA reference in the composite.xml to refer to the HeaderService.

  2. Define the custom header variable, manipulate it, and send it using bpelx:inputHeaderVariable, as shown in Example 6-71.

    Example 6-71 bpelx:inputHeaderVariable Use

    <variables>
      <variable name="input" messageType="tns:HeaderTestRequestMessage"/>
      <variable name="output" messageType="tns:HeaderTestResultMessage"/>
      <variable name="request" messageType="services:HeaderServiceRequestMessage"/>
      <variable name="response" messageType="services:HeaderServiceResultMessage"/>
      <variable name="customHeader"messageType="services:CustomHeaderMessage"/>
        </variables>
    ...
    <!-- initiate the remote process -->
      <invoke name="invokeAsyncService"
        partnerLink="HeaderService"
        portType="services:HeaderService" 
        bpelx:inputHeaderVariable="customHeader"
        operation="initiate"
        inputVariable="request"/>
    

6.20 Using MIME/DIME SOAP Attachments

A BPEL process service component can receive SOAP attachments in an optimized Message Transmission Optimization Mechanism (MTOM) format. However, the BPEL process cannot internally process the attachments. Instead, the attachments are added to the DOM as part of the XML file. Oracle recommends that you avoid using MTOM attachments and instead use Multipurpose Internet Mail Extensions (MIME) and Direct Internet Message Encapsulation (DIME) SOAP attachments.