Showing posts with label BPEL. Show all posts
Implementing Quartz Scheduler in JDeveloper to call BEPL
We will create a simple a web service proxy component, a scheduler job class that is called by the SOAScheduler and a java class SOASchedulerServlet that initiate the quartz scheduler.
1. To get started, create a new Application in JDeveloper by click CTRL-N, name it SOAScheduler,
2. select “Generic Application”.
3. Create a new Project named "SchedulerProject", select “Java” and “Web Services” as “Project Technologies”.
4. Click "Finish".
5. Create a new Web Service Proxy by click “File/New” or CRTL-N.
6. Click “OK” and “Next”.
7. Select “JAX-WS Style” and click “Next”.
8. Paste the WSDL location into “WSDL Document URL” and click “Next”.
9. Write “sample.oracle.otn.soascheduler.proxy” into “Package Name” and “sample.oracle.otn.soascheduler.proxy.types” into “Root Package for Generated Types” and click “Finish”.
10. In the new HelloWorldProcess_ptClient.java add the Line
System.out.println(helloWorldProcess.process("SOAScheduler"));
public static void main(String [] args)
{
helloworldprocess_client_ep = new Helloworldprocess_client_ep();
HelloWorldProcess helloWorldProcess = helloworldprocess_client_ep.getHelloWorldProcess_pt();
// Add your code to call the desired methods.
System.out.println(helloWorldProcess.process("SOAScheduler"));
}
11. Click on F11 or on the run icon . The composite will be executed by the new generated service proxy.
In the message window you will see the correct output of SOA example composite.
Add Quartz library to the project
1. Click on “Application” “Project Properties”, “Add JAR/Directory…”.
2. Select in your JDeveloper home “…\jdeveloper\soa\modules\quartz-all-1.6.5.jar”. Click “Select”.
3. Click “OK”.
Creating the Scheduler Job Component
1. Create a new “Java Class” in JDeveloper by click “File/New” or CRTL-N...
2. Click “OK”.
3. Set the Name to “HelloWorldJob” and Package to “sample.oracle.otn.soascheduler.job” and click “OK”.
4. Replace the generated source with the following lines.
package sample.oracle.otn.soascheduler.job;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import sample.oracle.otn.soascheduler.proxy.Helloworldprocess_client_ep;
import sample.oracle.otn.soascheduler.proxy.HelloWorldProcess;
import javax.xml.ws.WebServiceRef;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class HelloWorldJob implements Job{
@WebServiceRef
private static Helloworldprocess_client_ep helloworldprocess_client;
public HelloWorldJob() {
helloworldprocess_client = new Helloworldprocess_client_ep();
}
public void execute(JobExecutionContext jobExecutionContext) {
DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println("HelloWorldJob started");
try {
helloworldprocess_client = new Helloworldprocess_client_ep();
HelloWorldProcess helloWorldProcess = helloworldprocess_client.getHelloWorldProcess_pt();
// Add your code to call the desired methods.
System.out.println("HelloWorld Response: " + helloWorldProcess.process("SOAScheduler@" + df.format(date)));
} catch (Exception e) {
System.out.println("HelloWorld Process failed: " + e.toString());
e.printStackTrace();
}
}
}
Creating the SOASchedulerServlet java class
1. Create a new Java Class in JDeveloper by click “File/New” or CRTL-N...
2. Set the Name to “SOASchedulerServlet”, Package to “sample.oracle.otn.soascheduler”, Extends “javax.servlet.http.HttpServlet” and click on “OK”.
3. Replace the generated source with the following lines.
package sample.oracle.otn.soascheduler;
import sample.oracle.otn.soascheduler.job.HelloWorldJob;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;
public class SOASchedulerServlet extends HttpServlet {
StdSchedulerFactory schedFact;
Scheduler sched;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
schedFact = new StdSchedulerFactory("soa_quartz.properties");
sched = schedFact.getScheduler();
System.out.println(this.getClass().getName() + " started");
/*
// Add the holiday calendar to the schedule
AnnualCalendar holidays = new AnnualCalendar();
// fourth of July (July 4)
Calendar fourthOfJuly = new GregorianCalendar(2011, 7, 4);
holidays.setDayExcluded(fourthOfJuly, true);
// halloween (Oct 31)
Calendar halloween = new GregorianCalendar(2011, 9, 31);
holidays.setDayExcluded(halloween, true);
// christmas (Dec 25)
Calendar christmas = new GregorianCalendar(2011, 11, 25);
holidays.setDayExcluded(christmas, true);
// tell the schedule about our holiday calendar
sched.addCalendar("holidays", holidays, false, false);
*/
sched.start();
JobDetail jd = new JobDetail(JOB_NAME, GROUP_NAME, HelloWorldJob.class);
CronTrigger cronTrigger = new CronTrigger(TRIGGER_NAME, GROUP_NAME);
String cronExpr = null;
// Get the cron Expression as an Init parameter
cronExpr = getInitParameter("cronExpr");
System.out.println(this.getClass().getName() + " Cron Expression for " + JOB_NAME + ":" + cronExpr);
cronTrigger.setCronExpression(cronExpr);
System.out.println(this.getClass().getName() + " Scheduling Job " + JOB_NAME);
sched.scheduleJob(jd, cronTrigger);
System.out.println(this.getClass().getName() + " Job " + JOB_NAME + " scheduled.");
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
public void destroy() {
try {
if (sched != null) {
sched.unscheduleJob(TRIGGER_NAME, JOB_NAME);
sched.shutdown();
}
} catch (Exception e) {
System.out.println(this.getClass().getName() + " failed to shutdown: " + e.toString());
e.printStackTrace();
}
System.out.println(this.getClass().getName() + " stopped");
}
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
PrintWriter ajax = new PrintWriter(response.getOutputStream());
// logger.warning("get");
String action = request.getParameter("action");
if ("single".equals(action)) {
if (sched != null) {
try {
Trigger trigger =
new SimpleTrigger("SOASingleTrigger", GROUP_NAME, new Date());
trigger.setJobName(JOB_NAME);
trigger.setJobGroup(GROUP_NAME);
// Schedule the trigger
sched.scheduleJob(trigger);
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
} else if ("start".equals(action)) {
if (sched != null) {
try {
JobDetail jd = new JobDetail(JOB_NAME, GROUP_NAME, HelloWorldJob.class);
CronTrigger cronTrigger = new CronTrigger(TRIGGER_NAME, GROUP_NAME);
// Get the cron Expression as an Init parameter
String cronExpr = getInitParameter("cronExpr");
System.out.println(this.getClass().getName() + " Cron Expression for " + JOB_NAME + ":" + cronExpr);
cronTrigger.setCronExpression(cronExpr);
System.out.println(this.getClass().getName() + " Scheduling Job " + JOB_NAME);
sched.scheduleJob(jd, cronTrigger);
System.out.println(this.getClass().getName() + " Job " + JOB_NAME + " scheduled.");
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
} else if ("stop".equals(action)) {
if (sched != null) {
try {
sched.unscheduleJob(TRIGGER_NAME, GROUP_NAME);
System.out.println(this.getClass().getName() + " stopped");
} catch (Exception e) {
System.out.println(this.getClass().getName() + " failed to shutdown: " + e.toString());
e.printStackTrace();
}
}
}
ajax.println("<html>");
ajax.println(" <head>");
ajax.println(" <title>SOAScheduler - Web Interface</title>");
ajax.println(" <link rel=\"stylesheet\" type=\"text/css\" href=\"css/mystyle.css\"></link>");
ajax.println(" </head>");
ajax.println(" <body onload='startAjaxPeriodicalUpdater()'>");
ajax.println(" <h2>");
ajax.println(" SOAScheduler @");
ajax.println(" <span class=\"server\">" + System.getProperty("weblogic.Name") + "</span>");
ajax.println(" </h2>");
ajax.println("<table id=\"events_table\" class=\"events_table\" width=\"100%\">");
ajax.println("<tbody>");
String[] jobGroups;
String[] jobsInGroup;
String[] triggerGroups;
Trigger[] jobTriggers;
String[] calendersList;
AnnualCalendar calen;
CronTrigger cronTrigger;
int i, j, k;
try {
jobGroups = sched.getJobGroupNames();
triggerGroups = sched.getTriggerGroupNames();
calendersList = sched.getCalendarNames();
for (i= 0; i < calendersList.length; i++) {
calen = (AnnualCalendar)sched.getCalendar(calendersList[i]);
//System.out.println("Calendar: " + calendersList[i]);
ajax.printf("Calendar: " + calendersList[i]);
}
for (i = 0; i < jobGroups.length; i++) {
// System.out.println("Group: " + jobGroups[i] + " contains the following jobs");
jobsInGroup = sched.getJobNames(jobGroups[i]);
for (j = 0; j < jobsInGroup.length; j++) {
// System.out.println("- " + jobsInGroup[j]);
jobTriggers = sched.getTriggersOfJob(jobsInGroup[j], jobGroups[i]);
for (k = 0; k < jobTriggers.length; k++) {
// System.out.println("- " + triggersInGroup[j]);
if ("org.quartz.CronTrigger".equals(jobTriggers[k].getClass().getName())) {
cronTrigger = (CronTrigger)jobTriggers[k];
ajax.printf("<tr class=\"%s\"><td align=\"left\">Trigger: %s</td><td>Next: %s</td><td>Last: %s</td><td>Cron: %s</td></tr>",
"events", jobTriggers[k].getName(),
jobTriggers[k].getNextFireTime(),
jobTriggers[k].getPreviousFireTime(),
cronTrigger.getCronExpression());
} else {
ajax.printf("<tr class=\"%s\"><td align=\"left\">Trigger: %s</td><td>Next: %s</td></tr>",
"events", jobTriggers[k].getName(),
jobTriggers[k].getNextFireTime());
}
}
}
}
} catch (Exception e) {
System.out.println("SOASchdulerServlet failed: " + e.toString());
e.printStackTrace();
}
ajax.println("</tbody>");
ajax.println("</table>");
ajax.flush();
}
static final String GROUP_NAME = "SOAGroup";
static final String TRIGGER_NAME = "SOATrigger";
static final String JOB_NAME = "SOAJob";
static final String TARGET_PAGE = "index.jsp";
}
Create a quartz property file
1. Create a new File (General) in JDeveloper by click “File/New” or CRTL-N...
2. Select “File (General)”.
3. Set File Name to “soa_quartz.properties” and Directory to the src directory of your project. Click “OK”.
4. Insert the following lines into the property file.
#
# Configure Main Scheduler Properties
#
org.quartz.scheduler.instanceName = SOASchedulerorg.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#
# Configure ThreadPool
#
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 4
#
# Configure JobStore
#
org.quartz.jobStore.misfireThreshold = 5000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
Create a J2EE Deployment Descriptor (web.xml)
1. Create a new web.xml in JDeveloper by click “File/New” or CRTL-N...
2. Select “Java EE Deployment Descriptor”. Click “OK”.
3. Select “web.xml”. Click “Next”.
4. Select “2.5”. Click “Finish”.
5. Select “Servlets” and click on the green “+” (Create Servlet).
Set Name to “SOASchedulerServlet”, Servlet Class to “sample.oracle.otn.soascheduler.SOASchedulerServlet”. Set “Load Servlet on” to “Application Start”.
6. Select “Servlet Mappings” and click on the green “+” (Create “Servlet Mappings”). Add “/soaschedulerservlet” as URL Pattern.
7. Select “Initialization Parameters” and click on the green “+” (Create “Servlet Initialization parameters”). Add “cronExpr” as Name and “0 0,5,10,15,20,25,30,35,40,45,50,55 * * * ?” as Value.
8. Select “Pages” and click on the green “+” (Create “Welcome File”). Add “/soaschedulerservlet”.
9. The Source should look like this…
<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<servlet>
<servlet-name>SOASchedulerServlet</servlet-name>
<servlet-class>sample.oracle.otn.soascheduler.SOASchedulerServlet</servlet-class>
<init-param>
<param-name>cronExpr</param-name>
<param-value>0 0,5,10,15,20,25,30,35,40,45,50,55 * * * ?</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SOASchedulerServlet</servlet-name>
<url-pattern>/soaschedulerservlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/soaschedulerservlet</welcome-file>
</welcome-file-list>
</web-app>
10. Click “Save All”.
11. Attention: The name “cronExpr” is requested in the SOASchedulerServlet.java, and the value means, that the SOA composite bpel-101-helloworld is started every five minutes every day.
Create WAR File (Deployment Profile)
1. Create a new “WAR File” in JDeveloper by click “File/New” or CRTL-N...
2. Click “OK”.
3. Set the Profile Name to “SOAScheduler”. Click “OK”.
4. On the “General” tab set the “Web Context Root” to “SOAScheduler”.
5. On the Filters subtub of WEB-INF/lib deselect “quartz-all-1.6.5.jar”, because it is already available on the WebLogic Server 10.3.1/2/3. Click “OK”.
6. Click “OK”.
Deploy your application
1. Right click on your Project, select “Deploy” and click on “SOAScheduler”.
2. Select “Deploy to Application Server”. Click “Next”.
3. Select your Application Server, where the Oracle SOA Suite is installed. If you have not your application server already configured. Add a new connection with the green “+”. Click “Next”.
4. Select “AdminServer”. Click “Finish”.
If deployment successful, the message window shows following:
Fault Handling
Fault Handling
After completing this Lesson, you should be able to do the following:
- List the possible sources of faults
- Understand how to throw faults
- Understand the constructs available for making a process ‘fault tolerant’ - catch, catchAll
- Understand empty and terminate activities
- Understand compensation handler
- Understand Fault Policy Framework
What’s a Fault in BPEL
- In BPEL, a Fault is a disruption of process execution that results in a signal being sent from the system. Fault Handling is what we do when this happens.
- Fault Handling can be thought of as a "mode switch" from the normal processing of the scope or process.
- Its aim is to undo the partial and unsuccessful work of the scope in which the fault occurred.
Sources of Faults in BPEL process
nFaults in BPEL can be from various sources:
qA fault can be thrown automatically by the BPEL runtime environment, either due to a certain condition in the BPEL process itself (such as a join failure), as a consequence of error conditions in the runtime environment, or related to network communication or other reasons. For such situations, BPEL defines several System faults.
q
qA fault can occur when the BPEL process invokes a Web service operation. The operation might return a fault message, which results in a Business fault.
qA BPEL process can explicitly raise (throw) a custom fault, which is also a kind of Business fault.
When an event occurs that disrupts the normal flow of our business process, this is called a fault. How do we classify these faults? There are lots of ways that organizations classify faults, here is a simple one. Faults can be divided between those generated by our (or by our partner’s) Business Logic and those generated by the system at Runtime, either locally or remotely.Examples:When a fault is thrown, normal processing halts and control is sent to Fault Handler, if one is defined.
Taxonomy of Faults

nBPEL Standard Faults
§Are the faults that come directly from the BPEL Specification
nRuntime faults
§will not be defined by the user, so we need to design parts in the process to handle them. In bpel we will make use of the catch-activity for this. In the catch itself we can invoke our own fault-handling processes or do some other activities (retry etc) which are needed to get a valid situation again.
nBusiness Faults
§Are application specific faults and will occur when we use the “throw”-activity or if we invoke a partnerlink which returns with some fault. It’s up to the “business” to decide what needs to be done when the fault occurs and what activities are needed for handling it.
BPEL Standard Faults
nambiguousReceive
ncompletionConditionFailure
nconflictingReceive
nconflictingRequest
ncorrelationViolation
ninvalidBranchCondition
ninvalidExpressionValue
ninvalidVariables
njoinFailure
nmismatchedAssignmentFailure
nmissingReply
nmissingRequest
nscopeInitializationFailure
nselectionFailure
nsubLanguageExecutionFault
nuninitializedParterRole
nuninitializedVariable
nunsupportedReference
nxsltInvalidSource
nxlstStylesheetNotFound
Runtime Faults = Are generated by the system and includes all standard BPEL faults•invalid variable type used as a parameter (local)•site of the invoked service is temporarily down (remote)
Possible Binding Faults

Possible Remote Faults

Business Faults from partnerlinks
nInvoking synchronous operations on partner –provided Web services may return a WSDL fault message
qWSDL faults are identified in BPEL by their qualified name
nComprised of the WSDL's target namespace and the ncname of the fault

Business Faults = Use the Throw and ReThrow activities•invalid Customer number (local) throws a fault defined in our WSDL•credit check problems (remote) throws a fault defined in our partner’s WSDL Here we see an example of a fault that is thrown when a bad argument is used in a process. Starting at the top in the WSDL file: The portType is “CalculatorPortType”, the Operation is “CalculatorOperation”, and there are both input and output messages, “CalculatorInput” and “CalculatorOutput.” In this example, the fault’s name is “calcFault” and the Fault’s QName is “tns:BadArgumentFault”, which is defined somewhere in one of our other WSDL files.
Business Faults - Signaled (thrown) explicitly
nBPEL provides the <throw> activity
qSyntax <throw faultName="name" />
qBPEL does not require definition of fault names prior to their use in the <throw> activity
§This flexible approach can be error-prone, because there is no compile-time checking of fault names. In the case of typos, misspelled faults will not be handled by the designated fault handler.
qFaults can also have an associated variable that contains fault data
qIf such a variable is required, you have to specify it when throwing a fault, by using the optional faultVariable
§<throw faultName="name" faultVariable="variable-name" />
nThe throw activity has three elements: its name, the name of the faultName, and the faultVariable
qThe faultVariable is optional
qIn case a faultVariable is used, it has to be a messageType defined in the WSDL of the process. In other words, it cannot be a simpleType like string.

nThe faults raised with the <throw> activity have to be handled in the BPEL process.
nFaults that are not handled will be returned to the client if the process is synchronous, not otherwise
qIf you want to propagate the faults to the client,
nadd a fault messageType to WSDL, and then specify the <fault …> in operation element.
nIn a synchronous operation, the reply activity can return the fault.
nIn an asynchronous operation, the invoke activity performs this function. This is because in an asynchronous interaction, the client does not wait for a reply. The reply activity is not used to return a fault. Instead, the BPEL process returns a fault using a callback operation on the same port type that normally receives the requested information, with an invoke activity.
Making a fault tolerant process
nUse Fault handler
qUseful to handle standard faults, runtime faults (remote and binding), explicitly raised faults or faults coming from partnerlinks during a scope
qSo, whats left ?....notice the definition says “during a scope”. What if the fault occurs after current scope, say in a subsequent scope
nUse Compensation handler
qUseful if you want to undo a previously completed scope.
qDo I need to do fault handling from scratch, every time.
qNot really.
nUsing Fault Policy Framework
Handle commonly occurring faults in a central way
Handling Faults using Fault Handler
nA Fault handler can be associated with a scope. As the BPEL process can have multiple scopes and scope within scope, every scope can have its own fault handler
n
nWithin a fault handler, the business process defines custom activities that should recover from the fault and possibly reverse the partial (unsuccessful) work of the activity where the fault has occurred.
n
nBPEL Process can complete successfully even when there was a fault
nThis is possible if the fault is caught in a catch block of a scope
n
nOnce a scope receives a fault, normal processing of all nested activities is halted
nscope is considered to have ended abnormally
Designing a Fault Handler
nFault handlers provide a way to separate out normal process logic from error handling logic
nMakes normal processing logic less cluttered and therefore easier to read
nPosition fault handlers strategically
nCatch and handle all exceptions from where you want your process to recover
Now let's step back and look at fault handlers from a higher level. We don’t need Fault Handling, but we should have it. Like airbags and smoke alarms, you don’t need them, but they are highly recommended. Fault Handlers separate normal process logic from fault logic, i.e., the execution of normal activities vs. error handling logic that is in the Fault Handler. You should position your Fault Handlers strategically. By doing this, you don’t have to add fault logic for each individual activity, but rather only for logical units of work. This reduces the overall volume of fault handling code and makes the process less cluttered and much easier to read.
Position Fault Handlers at those points where you would want the process to recover from, or to, depending on how you look at it.
Adding the Fault Handler
nFault handlers can be defined
qFor the process
qFor a scope
qInline for the invoke activity

nTo handle the faults, catch and catchAll are used. These are placed within the FaultHandler

Here is the BPEL Fault Handler syntax.<faultHandlers>?<!-- Note: There must be at least one faultHandler --> <catch faultName="QName"? faultVariable="BPELVariableName"? ( faultMessageType="QName" | faultElement="QName" )? > activity </catch>* <catchAll>? activity </catchAll></faultHandlers>•If we declare a “faultHandlers” section we must have something inside that definition. Therefore, we need to define one or more Catches and/or a catchAll.
•If we define a Catch, it will optionally have a single associated faultName and optionally a single associated faultVariable.
•The faultVariable can also optionally have data that is of the faultMessageType or faultElement type.
•If you notice the “*” character after the closing angle bracket of the Catch, you can see that we can declare as many Catches as are needed.
•The catchAll is optional, and if we declare a catchAll, we can have only one. Both Catches and catchAlls have a primary activity to handle the actual fault recovery's actions.
catch Overview
nEach catch is created to handle a specific fault.
ncatch provides a flexible structure when it comes to matching catch to a fault
●
Type 1: By Fault Name only (which must be a globally unique QName)
Type 2: By FaultName and faultVariable type
Type 3: By faultVariable Type
nFault Variables must be explicitly defined inside the Catch that will handle that particular fault.
Catching a fault that has no variable or a fault that was not defined as such

Catching a fault that carries some data
nTo catch such a fault, we use a variable same in type as that of the fault. We can use the same variable itself or a variable with same type.
nAs discussed earlier, this variable has to of a messageType, that is defined in the WSDL

Catching a Remote Fault
nBPEL run-time faults can be caught as a named BPEL fault.

nWe can access the details of the fault by clicking on the green plus icon to create a fault variable
nUsing this faultVariable (which is of messageType RuntimeFaultMessage), the fault code, fault summary and details of the fault can be accessed.

catchAll Overview
nThe catchAll activity is provided to catch possible faults
nIf you use catchAll, you cannot access the fault variable as BPEL does not provide a method for obtaining additional information about the captured fault.
nUse the getFaultAsString() XPath extension function to obtain additional information.
<catchAll>
<sequence>
<assign>
<copy>
<from expression="ora:getFaultAsString()"/>
<to variable="outputVariable" part="payload"
query="/client:ErrorTesterProcessResponse/client:result"/>
</copy>
</assign>
</sequence>
</catchAll>
Terminate
nThe terminate activity immediately terminates the behavior of a business process instance within which the terminate activity is performed
Unhandled Exception
nIf no catch or catchAll is selected, the fault is not caught by the current scope and is rethrown to the immediately enclosing scope.
nIf the fault occurs in (or is rethrown to) the global process scope, and there is no matching fault handler for the fault at the global level, the process would error out.
nFor synchronous processes, this unhandled fault shall be returned to client
nFor asynchronous processes, an unhandled fault shall not be returned to client. The client will error out due to timeout.
nFor one way processes, the fault is not returned to client
Returning Faults from Sync and Async processes
nIf you want to return errors from synchronous processes that the client can handle,
qRecommended approach is to add fault message to WSDL and use the reply activity. Then add appropriate fault handler in client
qSimply throwing a fault without catching it is also an option, but it is comparatively difficult for the client to handle such an error (as no info is obtained from the WSDL)
nIf you want to return errors from asynchronous process to a client,
we must use a invoke activity. We need not have a separate porttype defined. The BPEL process returns a fault using a callback operation on the same port type that normally receives the requested information, with an invoke activity. (See http://download.oracle.com/docs/cd/B31017_01/integrate.1013/b28981/faults.htm#BABIBAFC). The client should have a pick activity to deal with different messages
No-op
nThere is often a need to use an activity that does nothing.
nAn example is when a fault must be caught and suppressed
nYou can use the empty activity to insert a no-op instruction into a business process
Interesting scenario
nA travel portal wants to offer a service TravelFlow that can book airline, car, hotel and tourism booking in one go. If any of the bookings cannot be done, nothing should get booked

Using Fault Handlers

A better approach would be….

….. Compensation
nThe fault-handling concept in BPEL is similar to exception-handling in Java and other programming languages. However, business processes require additional error- handling steps. When intermediate results are made persistent, they must be reversed explicitly. Let's now take a closer look at such compensation steps
Compensation Handler
nlet you specify compensation logic to undo successfully completed activities in the case of a fault.
nA compensation handler specifically defines how to reverse the result of the particular unit it's associated with.
nThe unit of compensation is, in its simplest form, one activity.
nIt can also be a BPEL scope that forms a logical unit of work consisting of several activities and therefore needs to be compensated as such.
When will it work
nDuring runtime processing, compensation handlers become active once the corresponding invoke activity or scope has completed successfully.
nA compensation handler never becomes active for an invoke activity or scope that terminated abnormally (for example, by means of a fault). If an invoke activity fails, BPEL presumes that no compensation is needed for the invoked service. In the case where a scope terminated abnormally, its fault handler must have taken care of compensating its nested activities already.
How will it work
nA snapshot of the data accessible to the invoke activity or scope at that point in time is taken.
nThis ensures that the compensation activity will ultimately have access to the same data that was current upon invocation of the original activity, so it can reverse what the original activity did.
How to trigger it
nIf you don't specify a fault handler or compensation handler for your activity or scope, there will be a default implementation
nDefault implementation - all active compensation handlers of activities enclosed by that scope are triggered
nBPEL also provides a special activity, the compensate activity, to explicitly trigger compensation handlers
nThis construct can only be used from within a fault handler or compensation handler.
nIt's applicable to immediately enclosed invoke activities and scopes only.
nUsing the scope attribute of the compensate activity, you select the unit to be compensated—that is, the name of the scope or invoke activity.
Fault Policy Management Framework
nThis framework gives us the opportunity to handle all the business and runtime faults for an “invoke” activity. With the framework we can define one policy for every bpel domain.
qSo, using this, you can say –
§ Whenever there is fault X, do this..
nThe framework cannot completely replace Fault Handlers or Compensation as it can only handle faults that are returned from partnerlinks
How to Implement
nDefine a bindings file in the composite fault-bindings.xml
nDefine a policy file in the composite fault-policies.xml
Both files are placed at same level as the composite.xml.
That’s it
If you want to use java actions,
nDeploy the java code onto the server, and then refer to it from the policy file.
n
Default available actions
nora-retry ( retry the activity )
nora-replay-scope ( replay the scope in which the fault occurred )
nora-rethrow-fault ( system will throw the fault to the bpel fault handlers )
nora-human-intervention ( the current activity will freeze. In the console the user will be able to take several actions on this
ninstance )
nora-terminate ( terminate instance )
nora-java ( execute custom java )
Dealing with Faults - Summary
Here are some of your options for dealing with faults
nUse a terminate activity to stop the execution of a process or an activity altogether so that somebody can step in and make the necessary repairs.
nUse a reply activity with a fault name associated with it so that it will respond with a fault.
nUse a throw activity to signal an internal fault.
nUse a fault handler to catch a fault and attempt to deal with it.
nUse compensation to rollback or "undo" a process that has failed after committing either itself as a whole (a microflow) or at least one of its activities (a long-running process).
For handling faults when invoking a partnerlink, one can use fault policy framework.
Challenge Exercise
nCreate a process that reads PO Data. PO Data contains header and lines. The process delivers two files – header.txt and lines.txt. If there is any issue in delivering lines.txt, header.txt should also be not delivered.
nHint: You should create two scopes, delivering one file in each scope, and add the compensation logic for the first scope.
nNote: You can attempt this exercise after we have discussed File adapters.
nCreate a process that inserts data into a database. After deploying the process, delete the table. So when you invoke the process it will error out. Use a fault policy framework to retry the error after 5 minutes. During this 5 minutes, create the table again. So that in next try, data will be inserted.
nFind out what happens when – in a flow activity containing two branches, one of the branches error out and the error goes unhandled in the branch, but is handled in a higher scope. If we have inserted a row in a table in the other branch, will it stay, or rollback.
nPlace the fault policy and binding files in MDS and use them in two composites.
Doing things Parallely Doing things Conditionally Doing things in a Loop Pick and OnAlarm
Doing things Parallely
Doing things Conditionally
Doing things in a Loop
Pick and OnAlarm
Lesson Objectives
nAfter completing this Lesson, you should be
able to do the following:
qAdd parallel flows using the Flow activity
qAdd conditional logic using Switch activity
qExecute loops using While activity
qCreating a web service bottom up
qUnderstand the use cases for Events
qHandle events using pick activity
qUsing a wait activity
qAdding OnAlarm branch to a scope
Processing with Parallel Flows
nA parallel flow:
qIs implemented in a BPEL <flow> structure
qContains one or more activity
sequences processed concurrently (in parallel)
qEnables synchronization of
dependencies between activities
qCompletes when all sequences in
the flow are finished
Parallel flows implement processing of concurrent sequences of activities. In BPEL the <flow> element implements the flow structure. The <flow> element may contain one or more activities to be processed simultaneously, that is, in parallel.
Typically, a sequence of activities are processed in parallel. Sequences of concurrent processing are enabled by nesting one or more activities within a <sequence> element, each of which are contained within the flow.Synchronization of activities is realized because the flow does not complete until all activities or sequences of activities are finished processing.
Parallel
Flow Example
nCreate
a process that takes in a string and returns its translation in French, German
and Russian languages.
qFor example, if input is Hello (English), then output is
Bonjour in French, Hallo in German
nIt
uses a translation service to do the job
n
nHowever,
as each of the translations are independent, this can be done parallely
Parallel Flow ExampleCreate a process that takes in a string and returns its translation in French, German and Russian languages.For example, if input is Hello (English), then output is Bonjour in French, Hallo in German and .. in Russian
Creating the Translation Service
nWe
want to create a simple web service that takes a string and translates it into
another language.
nThe
web service internally uses Google APIs to get the work done.
nThis
is an example of creating a web service bottom up – create the implementation
first and then generate the WSDL file
nCreate
the java file
nThen
use New > BusinessTier
> Web Services > Java Web Services to create the web service
nDeploy
to Application server
Adding a Parallel Flow to the Process
Drag a Flow activity from the
Component Palette and drop it into your process
nNote: The flow initially contains two
concurrent sequences.
Adding a Parallel Flow to the ProcessThe Component Palette contains a Flow activity. To add and configure a parallel flow in your process:1. Drag a Flow activity and drop it into the Diagram View. For example drop the flow after the AssignRating activity.2. Double-click the Flow activity to configure it. In the General tab, change the Name to GetPriceQuote. Click OK.Note: The flow is initially created with two branches. Each branch represents a sequence of activities to be processed in parallel. If you click the blue down-arrow icon, on the left of the diamond shape representing the flow, you can add additional branch sequences to the flow.
Conditional Branching with Switch
nIn BPEL a conditional branch:
qIs implemented by a <switch> element
qConsists of one or more ordered <case> branches, which
nSpecify a condition to be
evaluated
nAre processed in their order of
appearance, and the first branch with a true condition is processed
nContain a sequence of activities
qMay have one <otherwise> branch, which
nIs processed if all <case> conditions are false
nIs optional
nContains a sequence of activities
Conditional Branching with SwitchA conditional branch is structure used to take different processing paths based on some condition determined by the data values passed between activities in the process.BPEL implements conditional branching with the <switch> element, represented by the Switch activity in the Component Palette. A <switch> element can contain:One or more ordered <case> branches, each with a condition to be evaluated. The first <case> branch returning a true result is processed.Optionally, a <otherwise> branch, which is processed if no <case> branch is processed. If omitted the BPEL logic assumes an empty activity exists for the otherwise branch.In JDeveloper, when you drag a Switch activity from the Component Palette and drop it into the Diagram View the following two conditional branches are created:One <case> branch
An <otherwise> branchYou may add additional <case> branches as needed. Double-clicking the <case> branch allows you to specify a comment and a Boolean expression to be evaluated for the branch. All conditional branches contain a sequence of activities that can be processed when the branch is select for execution.
Adding Conditional Branching Logic
Using While for looping
nDrag a while activity into the process
nSpecify a condition. As long as condition is true, loop will
continue.
Use
cases
nI call a process, and expect it to return
different kinds of responses
nI call a DocumentService, that can return me either a PurchaseOrder or an Invoice or a Receipt
nI want multiple kinds of messages to be able
to initiate my BPEL process.
nI call a asynchronous process, but do not
want to wait indefinitely.
nI want to wait only for a certain
amount of time (say 5 minutes)
Hmm..so whats the common pattern?
nRealize that the first two scenarios can be
dealt with if I have an option to do different things depending upon the
message I receive
nThe third scenario is also similar if I
perceive the indication the system sends me when a particular amount of time
has passed as a message
nThe common pattern, hence, is event driven
processing
Taxonomy of Events
BPEL supports two types of events:
nMessage events are triggered by incoming messages
nAlarm events are time-related and are triggered either
after a certain duration or at a specific time.
Pick Activity
nThe
Pick activity is an excellent technique to use to implement a Receive activity
(wait for a message) with a timeout. This is accomplished by using both of the
following:
nAn onMessage branch to receive a specific
message from an operation exposed by a service through a PartnerLink
nAn onAlarm branch that implements a wait
time
nThe
Pick activity terminates when a message or an alarm event occurs, whichever
occurs first.
nPick
activity can be configured with multiple onMessage and onAlarm branches
Suspending a Process with a Wait Activity
nThe
Wait activity pauses for a specified amount of time or until a specified time
period.
nWaiting
for specified amount of time
q<wait name="Wait_1" for="'PT2M'"/>
qP1Y2M3DT4H5M6S – Wait for 1 year, 2 months, 3 days, 4 hours, 5
minutes and 6 seconds
nWaiting
until a certain time
q<wait name="Wait_2"
until="'2007-02-28T12:43:59'"/>
Raise the alarm, but still keep waiting
nWhile
I want to raise an alarm if the process doesn’t return after certain interval,
I still want to wait for the response
nUse
the On Alarm branch available to a scope.
nIf
any activity in a scope has to wait for more than the time configured in the On
Alarm branch, an alarm is raised.
Pick vs OnAlarm
nPick is a activity, OnAlarm is a
branch that can be added to any scope
nIn Pick, after the alarm, one of the paths
will be chosen. In OnAlarm,
after the alarm, just an alarm is raised, but no other action is done.
Notes
The Oracle BPEL Process Manager uses the open source Quartz Scheduler Library to implement the schedule expiration events for the wait and onAlarm branch of pick activities


































