Jarvis Pizzeria: Aborting a Process

In this blog entry, we will take a look at the way a dynamic process deals with a process that ends with an exception. We will implement this in our “Register Order” process.

We modeled the process as depicted below:

When saved, published and activated, we start a new dynamic process; of course through our famous form:

The expectation is that Register Order starts and that we can start executing the task. When we open the process and click the “Abort” button on the “Save in backend system”, the process ends with an error event. See the screenshot below:

So what do we expect our Dynamic Process to do? Will it recognize the error and re-activate the “Register Order” activity again? Let’s see.

Interesting to see is that the process is still running...Hmm...the “Error End” happens to not end the process, but instead just throw an error and end up in fault recovery. How do we know its still running? By having selected the filter in the activities list:

Let's try to end the process with a different callback.

Running this case and ending the human task with an abort action, the process at runtime looks like the following:

We can indeed see that the process came to an end, but far more interesting to see is that the Dynamic Process rules consider the process to be ended happily and activated two new activities: Process Payment and Prepare Pizza

So what have we learned? The Dynamic Process can’t handle two different callbacks. So if you would like to model a scenario in which the process aborts and the case should act upon the abort, you should work with case data to indicate the process ended not successfully. This also means that you should think about making processes repeatable to ensure that an aborted process can start again. So, look before you leap and happy modeling!

Disclaimer: please note that the human tasks we used in the above screenshots are of the “Submit” type, whereas you should use the “Accept-Reject” pattern.

Jarvis Pizzeria: Markers and Conditions

In this post we do a deep dive into the fundamentals of markers and conditions. But first one step back, what are markers and conditions and what do they have to do with each other?

For Dynamic Processes we recognize the following markers:

  • Repeatable: controls whether a stage, activity or milestone is repeatable.
  • Auto Complete: controls the completion of a stage instance.
  • Manually Activated: controls the activation of a stage or activity instance.
  • Required: controls whether a stage, activity or milestone is required.

Next we have the following conditions:

  • Activation: additional entry criteria for a stage.
  • Enablement: additional entry criteria for a activity.
  • Termination: additional exit criteria for a stage or activity.
  • Completion: addition exit criteria for a milestone.


Below is some additional information about these markers. This text comes directly from the Oracle documentation.


The behavior of the repetition relies on the presence of entry criteria. If there is no entry criterion defined, then the repetition rule is evaluated by default in the transition into the COMPLETED state. Otherwise the repetition rule is only evaluated, when an entry criterion is satisfied and the task/stage transitions away from the state AVAILABLE into the next state.

Repetition on completion

To repeat a task or stage when it gets completed a repetition rule must be defined and the task or stage must not have any entry criteria. Whenever a task or stage instance transitions into the COMPLETED state, the repetition rule is evaluated and if it evaluates to true a new instance of the task or stage is created. The new instance transitions into the AVAILABLE state.

Repetition triggered by entry criteria

A trigger for a repetition of a milestone, stage or task is a satisfied sentry, that is referenced as entry criterion. Whenever an entry criterion is satisfied, the repetition rule is evaluated and if it evaluates to true, a new instance of the milestone, stage or task is created. The new instance transitions into the AVAILABLE state. The previous instance, in case of a milestone instance, transitions in state COMPLETED and, in case of a stage or task instance, into the ACTIVE or ENABLED state (depending on the manual activation rule) because the entry criterion is satisfied.

Auto Complete

The attribute autoComplete controls the completion of a stage instance. The stage will be auto-completed if:

  • Auto-complete is true and there are no children in the ACTIVE state, and all required children are COMPLETED, DISABLED or TERMINATED.
  • Auto-complete is false and there are no children in the ACTIVE state and
    • all children are COMPLETED, DISABLED or TERMINATED, or
    • on manual completion, all required children are COMPLETED, DISABLED or TERMINATED.

Manually Activated

Whether the actual work of a task or stage can be performed depends on its entry criteria. Given that an entry criterion is fulfilled, there are two ways to activate a task:

  • By manual activation
  • By automatic activation

Manual activation is the default behavior in which it is required that a user manually activates a task. By specifying a manual activation rule, it is possible to omit this step or make it depend on case variable payload. With manual activation, a user can decide to activate a task or instead disable it. A task that is automatically activated must be carried out.
In terms of the task/stage lifecycle, manual activation corresponds to the transition from AVAILABLE to ENABLED when an entry criterion occurs, and from ENABLED to ACTIVE when the task is manually activated. In contrast, automatic activation corresponds to the direct transition from AVAILABLE to ACTIVE that fires immediately when an entry criterion occurs.


A plan item may be required, meaning that it has to reach an end-like state before the containing stage can complete. Whether a plan item is required can be specified by a required rule.
This rule is evaluated when the milestone, stage or task is instantiated and transitions to the state AVAILABLE, and its result value of type boolean is maintained throughout the remainder of the process instance. If this rule evaluates to true, the element's parent stage instance must not transition to COMPLETED state unless the element is in the COMPLETED, TERMINATED or DISABLED state. For example, a task that has not yet been worked on, i.e., is in state ENABLED, prevents its containing stage to complete. If the rule is not present, then it is considered to be false.


Below is some additional information about the conditions.


A task or stage becomes enabled as soon as any of its entry criteria is fulfilled. If this is given when the task/stage becomes available, it immediately becomes enabled or, depending on its manual activation rule, active.


The exit transition triggers when the task's/stage's exit criteria are met.

Our specification

The following image shows our current implementation.

Let's get into the details of this implementation.

A new instance of the Jarvis Pizzeria Dynamic Process is started by the Order Entry WebForm.

The Ordering stage has no entry condition, so this is activated immediately after the order has been given. This stage only contains a mandatory structured process that is started automatically. This structured process registers the order in a back-end system and is almost immediately completed. The completion of the activity also completes the Ordering stage (the ‘Auto Complete’ markers is set and there is no additional ‘Termination’ condition set).

The preparation stage has an access condition, namely: that the Ordering stage must be completed. That is the case, so the preparation stage is also activated immediately. This also causes that the structured process Prepare Pizza is enabled. Because it has to be activated manually, it is available but not yet started.

And finally also the Process Payment activity, that is not part of any stage, is enabled.

The following image shows this situation

We have now come to the point that the ordering is completed and that the order can be prepared. For this we have the structured process Prepare Pizza. For every ordered pizza in the order, an instance must be started manually. Let's start up an instance and see what happens.

We started the Prepare Pizza process. It has been completed at a certain moment. This also completes the Prepared milestone. This in turn results in the Compose Order activity to becoming available. The repeatable activity Prepare Pizza will also be available again.

It seemed to be so good, but this is not quite what we had in mind. It is not entirely logical that the milestone Prepared is set but also the Prepare Pizza activity is still available. The milestone can only be set as all pizza's has been prepared.
We have to adjust this. But now let's go on first. In order to complete the Preparation Stage, we must indicate that no more Pizzas needs to be prepared (DISABLE the Prepare Pizza activity) and that the order can be prepared (by executing the Compose Order activity).
After doing this we have the following situation

The Delivered milestone also appears to have no condition. So once the Delivery Stage is activated, the milestone is set, while the intention is that this only happens once the Deliver and Payment Activity has been completed. So there are some more adjustments needed.

We will implement the following adjustments:

  1. the Delivered milestone may only be set when both the Delivered activity and the Payment activity have been performed.
  2. the Prepared milestone may only be set if there is no Prepare Pizza activity available, but has been performed at least once.

Our implementation
1. For this change an entry condition for the Deliver milestone is needed. Initially, we decided that the milestone should be set as soon as the Delivered Activity is completed and the Paid milestone is set. However, the condition can only be based on milestones and activities in the own stage. The Paid milestone is therefore not available. Because it is possible to base the condition on Dynamic Process data, a good alternative is available. Payment is made in the Payment process. The condition can thus be provided with the check: amountPaid> 0.

2. This second condition does not seem to be that simple yet. The part that no Prepare Pizza activity may be available is simple. The activation criteria of the Prepared milestone must match 'Prepare Pizza' is DISABLED. But the other part is a bit harder. We have said that the activity must be performed at least once. But actually the activity has to be done exactly as often as the number of pizza in the order. Data objects are needed for the total number of instances (pizzas) and the number of instances executed. Once the value in these data objects is equal to each other, the criteria are met. This ensures that the Prepared milestone is available at the right moment.

But this does not prevent the Prepare Pizza activity from being started again (because it is still available) and the values ​​in the data objects no longer match each other. At this moment we do not have a good solution for this. In this way it is also not possible to prepare pizzas simultaneously (in parallel). This is also an issue we had with structured processes (26 Third step in Implementing the Order Processing, Correlation). It is our expectation that Oracle will come up with a solution to be able to execute business in parallel.
The Prepare Pizza activity is a manually starting activity. This is done with a reason. Now we could say: because the Pizza preparer starts the activity itself. But that is not the reason. The real reason is that the combination of automatic start and repeatable is quite an unfortunate one. As soon as an instance has been completed, the next one is started immediately. Because of this, it can not be DISABLED, so we can not meet the milestone condition.

After implementing these conditions we can rerun an instance and get in completed as expected.

Without going into the details of all the rather complex situations that can occur, we hope to have made clear with a few examples that the use of markers and conditions is not as simple as it seems. From a functional point of view, things can get complex fairly quick.

Jarvis Pizzeria: At the PaaS Forum

The annual Partner PaaS Forum was held in Budapest Hungary this year. The full Jarvis Pizzeria team attended the PaaS Forum and as always Jürgen delivered a great program with lots of interesting content.
On Monday, since last year in Split, the Community Day we got to take the stage and present about Jarvis Pizzeria and Dynamic Processes within the Oracle Integration Cloud. A great opportunity to show some of the highlight and content of our blog series. 

The next day was a day full with presentation from Oracle Product Management and at the end of the day the traditional awards were presented by Jürgen. We were both surprised and honoured to hear we received the Partner Community Award for outstanding PCS contributions. A great recognition of which we are very proud.

Besides all the great content and hands on labs that followed on the next three days, it was very nice to have several good conversation and interactions with the PCS team that flew in from San Francisco. It was very nice to meet Eduardo & Nicolas and share our feedback on the product in real life.
It is motivating to see that something really happens with our feedback. Things that require more effort have been put on the backlog or are as we speak under development, but many of the quick wins have already been processed. The results of this are already visible in the application.

Overall a great week as can be expected from the Partner Events, in case you missed it or you were there and want to learn more. Do not forget to sign up for the Summercamps, 27 to 31 august 2018, in Lisbon. 

Jarvis Pizzeria: The PCS Mobile app

PCS also comes with a mobile app for the end users. It’s available for iOS and Android devices (search for ‘Oracle Process Mobile’ in the PlayStore or the AppStore) . The app provides access to tasks in both connected and disconnected mode.

Compared to the browser features, there are a few differences. These are listed in the table below (this table comes directly from the oracle documentation).

But let's just have a look at how the app works. We have installed the app on an iPad 2017 and a Samsung Galaxy S8 phone.
Note: we already installed the app and configured it.

When starting the app, first thing you need to do is sign in. Nothing unusual so far. After that the ‘MyTasks’ list appears. On the S8 the filters are available underneath a button. On the iPad there is more space available, here are the filters directly available on the left side of the screen. depending on whether you hold the ipad horizontally or vertically, the filter may or may not be opened immediately.



From this screen it is very easy to sort and filter for tasks.
And once you've found the desired task to approve. You can directly approve the task without opening it, for that you can tick the task (checkbox or icon at the front of the task), and then click on approve. With this it is also possible to approve multiple tasks simultaneously.



Note: From here we will only show the screenshots of the iPad, but all shown functionality is also available on the S8, even if it will look a bit different.

Behind each task is a hamburger menu, via this menu it is possible for example to delegate a task or to reassign. When we click on a task, the task form is opened as we are also accustomed via the browser. All task functionality is available.

When we go back to the task list we also see a hamburger menu in the top left corner. Via this menu the other functionality of the app can be reached.

Let's look at the functionalities that are interesting for the end user. Namely starting applications and the process dashboard. The screenshots of the ipad show this. If you have experience with the browser version of PCS this will be very recognizable.

According to the table of differences, it would not be possible to view the dashboard. But as the picture above shows, that is now possible on the iPad. This is not yet the case on the S8.

We can conclude that the mobile app is a very useful application for the end user.
On the S8 things seem to be a bit off the screen, but we think this will have to do with the rounded screen on the sides.

Jarvis Pizzeria: Fourth step in Implementing the Order Processing, Decision Model

In our previous blog we gave an overview of the various type of decisions that are available for a Decision Model. In this blog we show by means of an example that Decision Models can also be used for making complex decisions. We are going to make a decision model that determines the order of preparation of the pizzas in an order.
The order of preparation is determined by the baking time, the total preparation time of each pizza and the number of available ovens (1 pizza per oven). Let's assume that we have an order for the following 9 pizzas:

  1. Small Margherita
  2. Large Margherita
  3. Small Pepperoni
  4. Medium Pepperoni
  5. Medium Pepperoni
  6. Large Pepperoni
  7. Small Quarttro Stagioni
  8. Medium Quarttro Stagioni
  9. Large Quarttro Stagioni

Expected outcome

The pizzas with the longest baking time are prepared first. When pizzas have the same baking time, the total preparation time is also taken into account to determine the order. As a result, to determine the sort order we first need to determine the baking time and total preparation time for each pizza. 
Because not all pizzas can be prepared at the same time, pizzas that are not in the oven will have a waiting time. Once we have established the order, we can also determine the waiting time per pizza. We explain this with the help of the figure below.

This image shows the desired output of the decision model when using 2 oven. Result is sorted based on the longest baking time and total preparation time. As soon as a pizza is baked, the next one is picked up. So as soon as the first one is finished, the third pizza is put in the oven, and as soon as the second one is finished, the fourth one is put in the oven. And then when the third is ready we go on with the fifth. And so on. Based on the sorting, however, the second has a shorter time as the first one. The order of the first two pizzas is therefore reversed. For the same reason, the order of the first 3 must be reversed for 3 ovens and the order of the first 4 for 4 ovens.
It may be difficult to see, but the waiting time for the different pizzas is determined as follows: - the first 2 can immediately go into the oven. They have no waiting time. - third waits for the first - fourth is waiting for the second - fifth waits for the first and third - sixth waits for second and fourth - seventh is waiting for first, third and fifth - eighth wait for second, fourth and sixth - ninth finally wait for first, third, fifth and seventh And for the completeness, when using 3 ovens we expect the following outcome:
And with 4 ovens:
For now we are determining the order of the pizzas within one of the orders, using this logic on multiple orders to determine what pizzas to prepare first is not supported yet.

Steps from Input to Output

Now lets see how to come from the input to the required output. We have the following steps to get from the input to the output:

  1. calculate baking time and total preparation time
  2. sort order by time
  3. apply sort order correction
  4. calculate waiting time

1. Calculate baking time and total preparation time

1.1 Pizza Level

We start by calculation the baking time. The baking time depends on the pizza type and size. For this we made a reusable function with a decisiontable in it.

For the duration another custom ‘getPreparationTime’’ function is used. This function determines how long it will take to prepare the pizza bottom or to add the filling.

Without getting into all the details, this function shows the usage of some default functions like ‘list’, ‘index of’, ‘number’ and ‘string’. This function returns 2 for a small pizza, 3 for a medium and 4 for a large pizza. When the size is none of these the functions return 0.

After getting the baking time the total duration can be determined. For this we have created a simple expression function.

1.2 Order Level

Now that we have defined the reusable functions to calculate the baking time and the total duration we need to apply these functions on the list of pizzas in the order.

Again we have defined a custom function. The function contains an expression with a for loop. For every pizza in the order, the following custom function (updatePizzaDetails) is called. In this call we also see that the previously defined functions for determining the times are used.

The ‘updatePizzaDetails’ function is a simple setter. A context with expressions.
Now we have also defined the function to perform the time calculations on the list. Calling this function is the last step for this part.
After calling this function we have the list that can be sorted.

2. Sort the order

For this, we will use the standard 'sort' operation. The sorting criteria that we use here are defined in a separate function.
The sorting criteria is in the Sorter.desc function.
Here we see, as mentioned earlier, that there is sorting on the baking time and on the total preparation time.

3. Sort order correction

At the expected output we have indicated that the order at the beginning of the list must be adjusted depending on the number of ovens. So first we have to define how many ovens there are. This can easily done by defining a 'constant' for the number of available ovens.
By changing this value, it is determined which of the above outputs the decision model gives. Next we defined a custom function with an if-then-else decision to correct the sort order.
Again we see the use of a number of standard functions. In this case all list related functions. In the 'then' part the first x-pizzas (depending on the number of ovens) are reversed. In the 'else' part the list remains unchanged. Normally, the list could simply be returned here, but this is currently not working properly. This results in a type casting error. As work-around the sublist function can be used, which also selects the entire list in our situation. Finally we have to apply this function on the order/list.

4. Calculate waiting time

As the fourth and last step, the waiting time has yet to be calculated. Earlier in this blog we have already indicated how the waiting time is calculated. This we have incorporated into a decision table. This is shown below. The point of attention in this table is the used hit policy. This is C. Which means as much as "The output consists of a list of all matching rules".

And ofcourse apply this function.

Expected outcome summarized

We have summarized these 4 steps in a context.
As outcome of the overall decision model we are only interested in the outcome of the fourth step. To complete the order, the customer data is also added. The final output of the complete decision model then becomes:

This output is available in the PCS process that is using the Decision Model.

Jarvis Pizzeria: The various Decisions of a Decision Model

In one of our next posts we will implement the Decision Model in the Order Process. Before we do that we first explain the various type of decisions that are available for a Decision Model.

The Decision Model editor in PCS (Process Cloud Service) or the later OIC (Oracle Integration Cloud) supports the DMN (Decision Modeling Notation) standard version 1.1, and uses FEEL (Friendly Enough Expression Language) to make decision modeling easier and more intuitive.

In DMN all decision logic is represented as ‘boxed expressions’. A ‘boxed expression’ is a graphical notation for decision logic. Within OIC we recognize the following boxed expressions:

The expressions in the boxes are FEEL expressions. A Decision Model is a tree of simple decisions notated as FEEL expressions. In the remainder of this blog we will give an example of the various boxed expressions.

The first example is a boolean expression with the name ‘SmallPizza’. The expression is true when the size of the pizza is ‘Small’. Otherwise it’s false.

In the second example we have the named (crustArea) expression to calculate the pizza crust area.

Next we have the if-then-else construction. Actually, this is no more than a combination of 3 expressions. The first determines which of the following 2 is returned as a result.

This construction could also be defined with the following single expression

Decision Table

The Decision Table is by far the most complex and ridge boxed expression. In this post we limit ourselves to a single example and an explanation of the available hit policies.

The following table returns the required baking time for each type of pizza. The baking time is independent of the size, except for the Quattro Stagioni, the Small pizza requires a minute less than the other sizes. To get the correct outcome from the Decision Table we have to set the hit policy. By default it is set to U(nique). But that will not work for this. There are 2 rules that a small Quarttro Stagioni meets. We want the first rule to be met. We do this by setting the hit policy to F(irst) in the upper left corner.

The following list shows the available Hit Policies. Here we are not going to treat them in detail.

The Unique hit policy is used when at most 1 rule can match the input
The Any hit policy is used when multiple rules can match the input, but the output value is the same for all matching rules
The First hit policy is used when multiple rules can match the input. The first hit by rule order is returned.
The Priority hit policy is used when multiple rules can match the input.The matching rule with the highest output priority is returned.The priority is defined by the order of output values in the decision table output column header
The Collect hit policy is used when multiple rules can match the input, and a list of output values for all the matching rules is desired
The Collect with sum hit policy is used when multiple rules can match the input, and the sum of the output values for all the matching rules is desired
The Collect with min hit policy is used when multiple rules can match the input, and the smallest output value for all matching rules is desired
The Collect with max hit policy is used when multiple rules can match the input, and the largest output value for all matching rules is desired
The Collect with count hit policy is used when multiple rules can match the input, and the count of the matching rules is desired

Next we come to the context box. A context is a list of key-value pairs.
In this example a list of 'constants'. The key must be unique, when duplicated, only the last one survives. In the example we used expressions, but it is possible to use any type that suits your needs, for example decision tables. In a context it is possible to reference entries that are defined higher in the context (like the fullname, that is using size and name).

A context is a list of key-value pairs and a list is a list of values without the key. It’s pretty straight forward.

Next is a relation. A relation is a shorthand for multiple contexts (a list of contexts).

Let’s convert this relation into a flat FEEL expression. We will do this in two steps. The first step is to present the relation as a list.

The next / second step is to transform this list into one single expression.

The last one is the function. Functions are used to get a reusable piece of code. You can feed them with parameters. A function can contain any of the other boxed types in its body. But that is not that special. Without explicitly mentioning it we already did it before. In the context we used nested expressions.

The following function checks whether the pizza size is 'Small', 'Medium' or 'Large'. If that is the case, the cooking time is calculated. For a 'Small' pizza that is 2, a 'Medium' 3 and for a 'Large' it is 4 minutes.

The ‘index of’ function returns all occurrences of the size in the list. For our solution this could only be one occurrence. We get this single occurrence as an entry in a list. That’s why the first entry is selected and convert to a string and thereafter into a number.
In this function we used a few of the available build-in functions. We won’t get into details about all of them in this blog. In a later blog we will pay special attention to these build-in functions.