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:
Section 7.1, "Introduction to Manipulating XML Data in BPEL Processes"
Section 7.2, "Delegating XML Data Operations to Data Provider Services"
Section 7.4, "Initializing a Variable with Expression Constants or Literal XML"
Section 7.6, "Accessing Fields Within Element-Based and Message Type-Based Variables"
Section 7.8, "Using Mathematical Calculations with XPath Standards"
Section 7.16, "Manipulating XML Data Sequences That Resemble Arrays"
Section 7.18, "Understanding the Differences Between Document-Style and RPC-Style WSDL Files"
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 7.18, "Understanding the Differences Between Document-Style and RPC-Style WSDL Files."This section provides an introduction to using XML data in BPEL processes.
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.
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 7-1 shows the formal syntax, as described in the Business Process Execution Language for Web Services Specification:
<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 7-2:
Example 7-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 7-3 provides an example:
<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 7.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 45, "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.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. The need to optionally perform 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 7-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 7-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 7-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
Oracle Fusion Middleware Tutorial for Running and Building an Application with Oracle SOA Suite describes 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.
The SDO binding component service provides the outside world with an entry point to the composite application, as shown in Figure 7-1.
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 4, "Introduction to the Functionality of the SOA Composite Editor."
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 7-2.
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.
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.
For more information, see Oracle Fusion Middleware Tutorial for Running and Building an Application with Oracle SOA Suite.
To create an entity variable and choose a partner link:
Go to the Structure window of the BPEL process service component in Oracle JDeveloper.
Right-click the Variables folder and select Expand All Child Nodes.
In the second Variables folder, right-click and select Create Variable.
The Create Variable dialog appears.
In the Name field, enter a name.
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.
Browse for and select the service for the Oracle ADF Business Component application.
Click OK to close the Partner Link Chooser and Create Variable dialogs.
The Create Variable dialog looks as shown in .
You now create a key to point to the order data in the Oracle ADF Business Component data provider service.
Drag a Bind Entity activity into your BPEL process service component.
The Bind Entity dialog appears.
In the Name field, enter a name.
To the right of the Entity Variable field, click the Search icon.
The Variable Chooser dialog appears.
Select the entity variable created in Section 7.2.1.3, "Creating an Entity Variable and Choosing a Partner Link" and click OK.
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.
Enter the details described in Table 7-2 to define the binding key:
Table 7-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:
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 |
Figure 7-4 shows the Specify Key dialog after completion.
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.
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.
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.
The syntax for declaring an SDO-based variable is similar to that for declaring BPEL variables. Example 7-4 provides details.
Example 7-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 7-4 is a regular DOM-based variable. Example 7-4 provides an example of the schema.
<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>
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 7-6 provides a simple example of converting from XML to SDO.
Example 7-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 7-7 provides an example of copying from an XPath expression of an SDO variable to a DOM variable.
Example 7-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 7-8 provides an example of removing a portion of SDO data.
<assign> <bpelx:remove> <bpelx:target variable="deptVar_s" query="hrtypes:Emp[2]" /> </bpelx:remove> </assign>
Note:
Thebpelx: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 need 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.
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.
Example 7-9 assigns a literal result
element to the payload
part of the output
variable:
Example 7-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>
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.
Example 7-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 7-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 7-11:
Example 7-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 7-12:
Example 7-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.
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.
In Example 7-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 7-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 7-14 shows how the BPEL file defines message type-based variables involved in this assignment:
Example 7-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 7-15:
Example 7-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 7-16:
Example 7-16 CreditRatingServiceRequestMessage Definition
<message name="CreditRatingServiceRequestMessage"> <part name="payload" element="tns:ssn"/> </message>
A BPEL process can also use element-based variables. In Example 7-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 7-17 Field Copying Levels
<assign> <copy> <from variable="input" part="payload" query="/tns:invalidLoanApplication/autoloan: application/autoloan:customer"/> <to variable="customer"/> </copy> </assign>
Example 7-18 shows how the BPEL file defines element-based variables involved in an assignment:
You can assign numeric values in XPath expressions.
Example 7-19 shows how to assign an XPath expression with the integer value of 100
.
You can use simple mathematical expressions like the one in Section 7.8.1, "How To Use Mathematical Calculations with XPath Standards," which increment a numeric value.
In Example 7-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 7-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 7-21:
You can assign string literals to a variable in BPEL.
The code in Example 7-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.)
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.
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 7-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 7-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.
You can assign boolean values with the XPath boolean function.
Example 7-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 7-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.
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.
Example 7-25 shows an example that uses the function getCurrentDate
.
Example 7-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 7-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
).
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.
The code in Example 7-27 fetches and copies the custId
attribute from this XML data:
Example 7-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 7-28 selects the custId
attribute of the customer field and assigns it to the variable custId
:
Example 7-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 7-29:
You can perform various operations on XML data in assign activities. The bpelx
extension types described in this section provide this functionality.
Note:
Thebpelx: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 7-30 provides an example.
Example 7-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 7-31 consolidates multiple bills of material into one single bill of material (BOM) by appending multiple b:part
s for one BOM to b:
part
s of the consolidated BOM.
Note:
Thebpelx: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 7-32 provides an example.
Example 7-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 7-33 shows the syntax before the execution of <insertBefore>
. The value of addrVar
is:
Example 7-33 Presyntax Execution
<a:usAddress> <a:state>CA</a:state> <a:zipcode>94065</a:zipcode> </a:usAddress>
Example 7-34 shows the syntax after the execution:
Example 7-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 7-35 shows the value of addrVar
:
Note:
Thebpelx: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 7-36 provides an example.
Example 7-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 7.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 7-37 shows the syntax before the execution of <insertAfter>
. The value of addrVar
is:
Example 7-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 7-38 shows the syntax after the execution:
Example 7-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 7-39 shows the value of 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>
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.
The bpelx:remove
extension in an assign activity enables a BPEL process service component to remove a variable. Example 7-40 provides an example.
Example 7-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 7-41 shows addrVar
with the following 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>
After executing the syntax shown in Example 7-42 in the BPEL process service component file, the second address line of Mailstop
is removed:
Example 7-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 7-43 in the BPEL process service component file, both address lines are removed:
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 7-44 provides an example.
Example 7-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 7-45:
Example 7-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 7-46:
Example 7-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 7-47 with xsi:type
info added to Peter Smith
:
<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 7-48 provides an example.
Example 7-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 7-49:
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 7-50 provides an example.
Example 7-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 7-51.
<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 7-52.
<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 7-53.
<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 7-54.
<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 7-55.
The bpelx:validate
function enables you to verify code and identify invalid XML data.
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" />
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.
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 7-56, addresses[1]
selects the first element of the addresses data sequence:
Example 7-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 7-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 7-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.
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 7-58 calculates the number of elements in the item
sequence and assigns it to the integer variable lineItemSize
.
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.
The dynamic indexing method shown in Example 7-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, [...]
).
<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.
The bpelx:append
extension in an assign
activity enables BPEL process service components to append new elements to an existing parent element. Example 7-60 provides an example.
Example 7-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.
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 7-61 under assign
demonstrate how to merge data sequences:
Example 7-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>
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 7-62 shows an append
statement initializing a purchase order (PO) document with 10
empty <lineItem>
elements under po
:
<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.
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.
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>
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.
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 7-63 provides an example:
Example 7-63 String to XML Element Conversion
<!-- execute the XPath extension function parseEscapedXML('<item>') and assign to a variable --> <assign> <copy> <from expression="ora:parseEscapedXML( '<item xmlns="http://samples.otn.com" sku="006"> <description>sun ultra sparc VI server </description> <price>1000 </price> <quantity>2 </quantity> <lineTotal>2000 </lineTotal> </item>')"/> <to variable="escapedLineItem"/> </copy> </assign>
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 7-64:
Example 7-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 7-65:
Example 7-65 RPC-Style type Definition
<message name="LoanFlowRequestMessage"> <part name="payload" type="s1:LoanApplicationType"/> </message>
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 7-65). In document-style, the top-level node is the element name (for example, loanApplication
).
Example 7-66 and Example 7-67 show what an XPath query string looks like if an application named LoanServices
were in RPC style.
Example 7-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>
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 7-68:
Example 7-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 ..." .../>
This section provides an example of how to create BPEL and WSDL files to receive SOAP headers.
To receive SOAP headers in BPEL:
Create a WSDL file that declares header messages and the SOAP binding that binds them to the SOAP request. Example 7-69 provides an example.
Example 7-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>
Create a BPEL source file that declares the header message variables and uses bpelx:headerVariable
to receive the headers, as shown in Example 7-70.
Example 7-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 requestor --> <receive name="receiveInput" partnerLink="client" portType="tns:HeaderService" operation="initiate" variable="input" bpelx:headerVariable="customHeader" createInstance="yes"/>
This section provides an example of how to send SOAP headers.
Define an SCA reference in the composite.xml
to refer to the HeaderService
.
Define the custom header variable, manipulate it, and send it using bpelx:inputHeaderVariable
, as shown in Example 7-71.
Example 7-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"/>
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.