Open the BPEL process that was used in the Time for action – adding scopes section and follow the ensuing steps:
<invoke>
activity looks like the following screenshot:<scope>
activity and create a fault handler with a <catch>
construct:<scope>
activity looks as follows:In this section, we discuss the inner structure of the <scope>
activity. We discuss defining local variables, partner links, handlers, and so on.
We can specify <partnerLinks>
, <messageExchanges>
, <variables>
, <correlationSets>
, <faultHandlers>
, <compensationHandler>
, <terminationHandler>
, and <eventHandlers>
locally for the scope, as shown in the following code. All are optional.
<scope> <partnerLinks> <!-- Local partner links definition --> </partnerLinks> <messageExchanges> <!-- Local message exchanges --> </messageExchanges> <variables> <!-- Local variables --> </variables> <correlationSets> <!-- Local correlation sets --> </correlationSets> <faultHandlers> <!-- Fault handlers local to scope. --> </faultHandlers> <compensationHandler> <!-- Local compensation handlers.--> </compensationHandler> <terminationHandler> <!-- Local termination handler. --> </terminationHandler> <eventHandlers> <!-- Local event handlers. --> </eventHandlers> activity </scope>
Inner structure of a scope is similar to an overall BPEL process definition. However, there are several differences, as follows:
<process>
construct cannot contain <process>
as it is not an activity. However, the <scope>
can.<scope>
construct, not for a <process>
construct.<scope>
supports concurrent access to its shared resources such as variables and correlation sets. However, the <process>
construct has no such support. We explain about this in the Isolated scopes section.Based on the defined local variables, partner links, and so on, the behavior of the activities is defined within the scope changes, so we can say a <scope>
activity provides behavioral contexts for the enclosed activities.
Let's realize what we discussed with an example scope activity with an inline fault handler. This sample was introduced in the Inline fault handling section in Chapter 6, Fault Handling and Signaling. The primary activity of the scope is <invoke>
and the faults generated within the <invoke>
activity are handled by the inline fault handler. The primary activity of a <scope>
activity can be either a behavioral activity such as <invoke>
or a structural activity such as <sequence>
, <scope>
, and <flow>
, as shown in the following code:
<!-- Synchronously invoke the Book Warehousing Web Service --> <scope name="BookWarehousingInvoke"> <faultHandlers> <catchAll> <assign> <copy> <from expression="false()"/> <to variable="WarehousingServicePartnerLink_OutputVariable" />" part="warehouseSuccessed"/> </copy> </assign> </catchAll> </faultHandlers> <invoke partnerLink="WarehousingServicePartnerLink" portType="ns3:Warehousing_porttype" operation="WarehouseOperation" inputVariable="WarehousingServicePartnerLink_InputVariable" outputVariable="WarehousingServicePartnerLink_OutputVariable" /> </scope>
If the enclosed primary activity of the <scope>
activity is a structured activity such as <sequence>
or <scope>
, it can have many child activities and the depth of the tree is arbitrary.
The variables defined within <scope>
are only visible to the enclosed activities. So, there can be multiple variables with the same name but in different scopes that are not enclosed with each other. This rule is applied for any resource such as partner links and correlation sets.
When it comes to handlers, such as fault handler, it handles the faults generated from all the enclosed activities. The faults that are not caught by the inline fault handler are thrown to the enclosing <scope>
or <process>
activity.
Similar to fault handlers, compensation handlers, event handlers, termination handlers, and so on, can be defined within the <scope>
activity. In the next section, we will introduce those handlers. Also the event handling and compensation handling are discussed in detail as separate chapters (Chapter 10, Events and Event Handlers, and Chapter 11, Compensations).
There are four types of handlers that can be installed within a <scope>
activity. They are as follows:
Out of these four, the fault handler and event handler can be immediately enclosed within a <process>
activity as well. However, the compensation handler and termination handler is not allowed to be installed within a <process>
activity.
We discussed the fault handler in Chapter 6, Fault Handling and Signaling, in detail. We discussed how to signal faults and handle faults within the <scope>
activity:
<!-- Synchronously invoke the Book Warehousing Web Service --> <scope name="BookWarehousingInvoke"> <faultHandlers> <catchAll> <!—Fault Handling Logic--> </catchAll> </faultHandlers> <invoke … /> </scope>
As a fault handler is triggered by a signaled fault, an event handler is triggered when the corresponding event occurs. Those events are twofold. An event can be generated due to an incoming message that corresponds to a WSDL operation, or they can be due to a user-defined alarm. An alarm can be configured to fire at a specific point in time or after a specific amount of time period. Also, an alarm can be configured to repeatedly trigger each time the duration period expires, as shown in the following code:
<scope name="bookWareHousingProcess" > <eventHandlers> <!-- Alarm triggers when a message that correspond to a WSDL operation--> <onEvent partnerLink="QueryServiceClientPartnerLink" operation="searchOperationStatus" ...> <scope>...</scope> </onEvent> <!-- Alarm triggers after one hour--> <onAlarm> <for>'P0DT1H'</for> <scope>...</scope> </onAlarm> </eventHandlers> </scope>
We will discuss event handlers in detail in Chapter 10, Events and Event Handlers.
When an error occurs, some of the work already done has to be undone. The compensation handler comes into play in such scenarios. We discuss compensation handlers in detail in Chapter 11, Compensations. The following code is an example:
<scope> <compensationHandler> <!--Undo logic--> <invoke name="withdrawSubmition" ... /> </compensationHandler> <invoke name="submit" ... /> </scope>
A scope can be terminated forcefully when the scope or process enclosing it has faulted or the <forEach>
activity, that enclosing a scope, can also forcefully terminate it. In such a scenario, the termination handler supports a customized termination behavior such as sending a notification to its client or garbage cleanup, as follows:
<scope> <terminationHandler> <!-- termination logic --> </terminationHandler> <sequence> <!-- business logic --> </sequence> </scope>
In the preceding sections, we introduced the functionality of the <scope>
activity. We discussed how to define local variables, partner links, handlers, and so on. Also, we mentioned that the activities enclosed within a <scope>
activity can access the shared variables, partner links, and so on, which are defined in a parent <scope>
activity or in the global level. There can be scenarios that involve several <scope>
activities that concurrently access the shared global variables, partner links, and so on. In such situations, there should be some concurrency control to avoid conflicting situations due to concurrent accesses.
WS-BPEL 2.0 defines the concept of isolated scopes, which supports concurrency control over shared global variables, partner links, and dependency links. In this section, we are going to discuss concurrency control feature in the <scope>
activity. Isolated scopes ensure that the results of each <scope>
activity are equal if the conflicting activities on shared resources are reordered in any possible sequence.
There will be no conflict states in the BPEL process due to concurrent access of shared resources by isolated scopes. The semantics of isolated scopes are similar to the isolation level called serializable, which is the highest isolation level in the concurrency control.
Let's learn how to define an isolated scope. There is only one attribute named isolated
to configure an isolated scope. Consider the following example, where two <scope>
activities within a <flow>
activity access the same global variable called global
:
<process ...> <variables> <variable name="global" element="..." /> </variables> <flow> <scope name="S1" isolated="yes"> <sequence> ... <invoke ... outputVariable="global" /> ... </sequence> </scope> <scope name="S2" isolated="yes"> <sequence> ... <assign> <copy> <from>...</from> <to variable="global" /> </copy> </assign> ... </sequence> </scope> </flow> </process>
Now, you have an idea on how the <scope>
activities can be used in BPEL processes and how to use a fault handler and a termination handler within a <scope>
activity.
In this section, you should restructure the complete book warehousing process and add relevant fault handlers to each external web service invocation taking place.
Q1. Find the correct sentences regarding the isolated scopes.
Q2. What are the handlers that are only allowed within a <scope>
activity?
<faultHandler>
<compensationHandler>
<eventHandler>
<terminationHandler>
Q3. What constructs are not allowed within a <scope>
activity?
<sequence>
<import>
<extensions>
<variables>
Q4. Select the possible local variable declarations out of the following: