diff --git a/docs/docusaurus/docs/bpmn/ch02-GettingStarted.md b/docs/docusaurus/docs/bpmn/ch02-GettingStarted.md index 3636cc0f2db..01437469b2e 100644 --- a/docs/docusaurus/docs/bpmn/ch02-GettingStarted.md +++ b/docs/docusaurus/docs/bpmn/ch02-GettingStarted.md @@ -43,15 +43,15 @@ The example we’ll build is a simple *holiday request* process: First, we create a new Maven project through *File → New → Other → Maven Project* -![getting.started.new.maven](assets/bpmn/getting.started.new.maven.png) +![getting.started.new.maven](../assets/bpmn/getting.started.new.maven.png) In the next screen, we check '*create a simple project (skip archetype selection)*' -![getting.started.new.maven2](assets/bpmn/getting.started.new.maven2.png) +![getting.started.new.maven2](../assets/bpmn/getting.started.new.maven2.png) And fill in some *'Group Id'* and *'Artifact id'*: -![getting.started.new.maven3](assets/bpmn/getting.started.new.maven3.png) +![getting.started.new.maven3](../assets/bpmn/getting.started.new.maven3.png) We now have an empty Maven project, to which we’ll add two dependencies: @@ -126,11 +126,11 @@ The **ProcessEngine** object is then created using this configuration (line 17). You can now run this. The easiest way in Eclipse is to right-click on the class file and select *Run As → Java Application*: -![getting.started.run.main](assets/bpmn/getting.started.run.main.png) +![getting.started.run.main](../assets/bpmn/getting.started.run.main.png) The application runs without problems, however, no useful information is shown in the console except a message stating that the logging has not been configured properly: -![getting.started.console.logging](assets/bpmn/getting.started.console.logging.png) +![getting.started.console.logging](../assets/bpmn/getting.started.console.logging.png) Flowable uses [SLF4J](http://www.slf4j.org/) as its logging framework internally. For this example, we’ll use the log4j logger over SLF4j, so add the following dependencies to the pom.xml file: @@ -155,7 +155,7 @@ Log4j needs a properties file for configuration. Add a *log4j.properties* file t Rerun the application. You should now see informative logging about the engine booting up and the database schema being created in the database: -![getting.started.console.logging2](assets/bpmn/getting.started.console.logging2.png) +![getting.started.console.logging2](../assets/bpmn/getting.started.console.logging2.png) We’ve now got a process engine booted up and ready to go. Time to feed it a process! @@ -170,7 +170,7 @@ these different steps to each other. Through this, the BPMN 2.0 standard allows The process definition we’ll use is the following: -![getting.started.bpmn.process](assets/bpmn/getting.started.bpmn.process.png) +![getting.started.bpmn.process](../assets/bpmn/getting.started.bpmn.process.png) The process should be quite self-explanatory, but for clarity’s sake let’s describe the different bits: @@ -358,7 +358,7 @@ Using the task identifier, we can now get the specific process instance variable Which, if you run this, should look something like this: -![getting.started.console.logging3](assets/bpmn/getting.started.console.logging3.png) +![getting.started.console.logging3](../assets/bpmn/getting.started.console.logging3.png) The manager can now **complete the task**. In reality, this often means that a form is submitted by the user. The data from the form is then passed as *process variables*. Here, we’ll mimic this by passing a map with the 'approved' variable (the name is important, as it’s used later on in the conditions of the sequence flow!) when the task is completed: @@ -400,7 +400,7 @@ When the *execution* arrives at the *service task*, the class that is referenced When running the example now, the logging message is shown, demonstrating the custom logic is indeed executed: -![getting.started.console.logging4](assets/bpmn/getting.started.console.logging4.png) +![getting.started.console.logging4](../assets/bpmn/getting.started.console.logging4.png) ### Working with historical data diff --git a/docs/docusaurus/docs/bpmn/ch04-API.md b/docs/docusaurus/docs/bpmn/ch04-API.md index d07b8951a02..6234d4b446c 100644 --- a/docs/docusaurus/docs/bpmn/ch04-API.md +++ b/docs/docusaurus/docs/bpmn/ch04-API.md @@ -7,7 +7,7 @@ title: The Flowable API The engine API is the most common way of interacting with Flowable. The main starting point is the ProcessEngine, which can be created in several ways as described in the [configuration section](bpmn/ch03-Configuration.md#creating-a-processengine). From the ProcessEngine, you can obtain the various services that contain the workflow/BPM methods. ProcessEngine and the services objects are thread safe, so you can keep a reference to one of those for a whole server. -![api.services](assets/bpmn/api.services.png) +![api.services](../assets/bpmn/api.services.png) ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); @@ -211,7 +211,7 @@ The methods follow the naming convention of the regular process variables: The following BPMN diagram shows a typical example: -![api.transient.variable.example](assets/bpmn/api.transient.variable.example.png) +![api.transient.variable.example](../assets/bpmn/api.transient.variable.example.png) Let’s assume the 'Fetch Data' service task calls some remote service (for example, using REST). Let’s also assume some configuration parameters are needed and need to be provided when starting the process instance. Also, these configuration parameters are not important for historical audit purposes, so we pass them as transient variables: @@ -475,27 +475,27 @@ When using the in-memory H2 database for unit tests, the following instructions Suppose we have put a *breakpoint* somewhere in our unit test (in Eclipse this is done by double-clicking in the left border next to the code): -![api.test.debug.breakpoint](assets/bpmn/api.test.debug.breakpoint.png) +![api.test.debug.breakpoint](../assets/bpmn/api.test.debug.breakpoint.png) If we now run the unit test in *debug* mode (right-click in test class, select 'Run as' and then 'JUnit test'), the test execution halts at our breakpoint, where we can now inspect the variables of our test as shown in the right upper panel. -![api.test.debug.view](assets/bpmn/api.test.debug.view.png) +![api.test.debug.view](../assets/bpmn/api.test.debug.view.png) To inspect the Flowable data, open up the *'Display'* window (if this window isn’t there, open Window→Show View→Other and select *Display*.) and type (code completion is available) org.h2.tools.Server.createWebServer("-web").start() -![api.test.debug.start.h2.server](assets/bpmn/api.test.debug.start.h2.server.png) +![api.test.debug.start.h2.server](../assets/bpmn/api.test.debug.start.h2.server.png) Select the line you’ve just typed and right-click on it. Now select 'Display' (or execute the shortcut instead of right-clicking) -![api.test.debug.start.h2.server.2](assets/bpmn/api.test.debug.start.h2.server.2.png) +![api.test.debug.start.h2.server.2](../assets/bpmn/api.test.debug.start.h2.server.2.png) Now open up a browser and go to [](http://localhost:8082), and fill in the JDBC URL to the in-memory database (by default this is jdbc:h2:mem:flowable), and hit the connect button. -![api.test.debug.h2.login](assets/bpmn/api.test.debug.h2.login.png) +![api.test.debug.h2.login](../assets/bpmn/api.test.debug.h2.login.png) You can now see the Flowable data and use it to understand how and why your unit test is executing your process in a certain way. -![api.test.debug.h2.tables](assets/bpmn/api.test.debug.h2.tables.png) +![api.test.debug.h2.tables](../assets/bpmn/api.test.debug.h2.tables.png) ## The process engine in a web application diff --git a/docs/docusaurus/docs/bpmn/ch06-Deployment.md b/docs/docusaurus/docs/bpmn/ch06-Deployment.md index 85a5bc80a2e..4a61868cf35 100644 --- a/docs/docusaurus/docs/bpmn/ch06-Deployment.md +++ b/docs/docusaurus/docs/bpmn/ch06-Deployment.md @@ -211,7 +211,7 @@ If no image is provided in the deployment, as described in the [previous section The resource can be retrieved in exactly the same way as when [an image is provided](bpmn/ch06-Deployment.md#providing-a-process-diagram) in the deployment. -![deployment.image.generation](assets/bpmn/deployment.image.generation.png) +![deployment.image.generation](../assets/bpmn/deployment.image.generation.png) If, for some reason, it’s not necessary or desirable to generate a diagram during deployment, the isCreateDiagramOnDeploy property can be set on the process engine configuration: diff --git a/docs/docusaurus/docs/bpmn/ch07a-BPMN-Introduction.md b/docs/docusaurus/docs/bpmn/ch07a-BPMN-Introduction.md index b5915956185..310788c2c78 100644 --- a/docs/docusaurus/docs/bpmn/ch07a-BPMN-Introduction.md +++ b/docs/docusaurus/docs/bpmn/ch07a-BPMN-Introduction.md @@ -15,7 +15,7 @@ BPMN is a widely accepted and supported standard notation for representing proce Create a new XML file (*right-click on any project and select New→Other→XML-XML File*) and give it a name. Make sure that the file **ends with .bpmn20.xml or .bpmn**, otherwise the engine won’t pick it up for deployment. -![new.bpmn.procdef](assets/bpmn/new.bpmn.procdef.png) +![new.bpmn.procdef](../assets/bpmn/new.bpmn.procdef.png) The root element of the BPMN 2.0 schema is the definitions element. Within this element, multiple process definitions can be given (although our advice is to have only one process definition in each file, as this simplifies maintenance later in the development process). An empty process definition looks like the one shown below. Note that the minimal definitions element only needs the xmlns and targetNamespace declaration. The targetNamespace can be anything and is useful for categorizing process definitions. @@ -68,7 +68,7 @@ The use case is straightforward: we have a company, let’s call it BPMCorp. In The business process as described above can be defined graphically using the [Flowable Designer](bpmn/ch13-Designer.md#eclipse-designer). However, for this tutorial, we’ll type the XML ourselves, as we’ll learn the most this way at this stage. The graphical BPMN 2.0 notation of our process looks like this: -![financial.report.example.diagram](assets/bpmn/financial.report.example.diagram.png) +![financial.report.example.diagram](../assets/bpmn/financial.report.example.diagram.png) What we see is a [none Start Event](bpmn/ch07b-BPMN-Constructs.md#None-start-event) (circle on the left), followed by two [User Tasks](bpmn/ch07b-BPMN-Constructs.md#user-task): *'Write monthly financial report'* and *'Verify monthly financial report'*, ending in a [none end event](bpmn/ch07b-BPMN-Constructs.md#None-end-event) (circle with thick border on the right). @@ -158,7 +158,7 @@ After the task is created, the startProcessInstanceByKey method will return beca We can now throw this all together and create a simple Java program. Create a new Eclipse project and add the Flowable JARs and dependencies to its classpath (these can be found in the *libs* folder of the Flowable distribution). Before we can call the Flowable services, we must first construct a ProcessEngine that gives us access to the services. Here we use the *'standalone'* configuration, which constructs a ProcessEngine that uses the database also used in the demo setup. -You can download the process definition XML [here](assets/bpmn/FinancialReportProcess.bpmn20.xml). This file contains the XML shown above, but also contains the necessary BPMN [diagram interchange information](bpmn/ch06-Deployment.md#generating-a-process-diagram) to visualize the process in the Flowable tools. +You can download the process definition XML [here](../assets/bpmn/FinancialReportProcess.bpmn20.xml). This file contains the XML shown above, but also contains the necessary BPMN [diagram interchange information](bpmn/ch06-Deployment.md#generating-a-process-diagram) to visualize the process in the Flowable tools. public static void main(String[] args) { @@ -202,11 +202,11 @@ We could also use the task query API to get the same results using the name of t As we’ve configured our ProcessEngine to use the same database that the demo setup is using, we can now log into the [Flowable IDM](http://localhost:8080/flowable-idm/). Login as admin/test and create 2 new users *kermit* and *fozzie*, and give both of them the *Access the workflow application* privilege. Then create 2 new organization groups named *accountancy* and *management*, and add fozzie to the new accountancy group and add kermit to the management group. Now login with fozzie to the [Flowable task](http://localhost:8080/flowable-task/) application, and we will find that we can start our business process by selecting the Task App, then its *Processes* page and selecting the *'Monthly financial report'* process. -![bpmn.financial.report.example.start.process](assets/bpmn/bpmn.financial.report.example.start.process.png) +![bpmn.financial.report.example.start.process](../assets/bpmn/bpmn.financial.report.example.start.process.png) As explained, the process will execute until reaching the first user task. As we’re logged in as fozzie, we can see that there is a new candidate task available for him after we’ve started a process instance. Select the *Tasks* page to view this new task. Note that even if the process was started by someone else, the task would still be visible as a candidate task to everyone in the accountancy group. -![bpmn.financial.report.example.task.assigned](assets/bpmn/bpmn.financial.report.example.task.assigned.png) +![bpmn.financial.report.example.task.assigned](../assets/bpmn/bpmn.financial.report.example.task.assigned.png) ### Claiming the task @@ -220,7 +220,7 @@ The task is now in the **personal task list of the user that claimed the task**. In the Flowable Task app, clicking the *claim* button will call the same operation. The task will now move to the personal task list of the logged on user. You’ll also see that the assignee of the task changed to the current logged in user. -![bpmn.financial.report.example.claim.task](assets/bpmn/bpmn.financial.report.example.claim.task.png) +![bpmn.financial.report.example.claim.task](../assets/bpmn/bpmn.financial.report.example.claim.task.png) ### Completing the task diff --git a/docs/docusaurus/docs/bpmn/ch07b-BPMN-Constructs.md b/docs/docusaurus/docs/bpmn/ch07b-BPMN-Constructs.md index 4e0273f726f..801b54740ff 100644 --- a/docs/docusaurus/docs/bpmn/ch07b-BPMN-Constructs.md +++ b/docs/docusaurus/docs/bpmn/ch07b-BPMN-Constructs.md @@ -172,15 +172,15 @@ The default value for this is attribute is *"global"*. The following is an example of two separate processes communicating using signals. The first process is started if an insurance policy is updated or changed. After the changes have been reviewed by a human participant, a signal event is thrown, signaling that a policy has changed: -![bpmn.signal.event.throw](assets/bpmn/bpmn.signal.event.throw.png) +![bpmn.signal.event.throw](../assets/bpmn/bpmn.signal.event.throw.png) This event can now be caught by all process instances that are interested. The following is an example of a process subscribing to the event. -![bpmn.signal.event.catch](assets/bpmn/bpmn.signal.event.catch.png) +![bpmn.signal.event.catch](../assets/bpmn/bpmn.signal.event.catch.png) **Note:** it’s important to understand that a signal event is broadcast to **all** active handlers. This means, in the case of the example given above, that all instances of the process catching the signal will receive the event. In this scenario, this is what we want. However, there are also situations where the broadcast behavior is unintended. Consider the following process: -![bpmn.signal.event.warning.1](assets/bpmn/bpmn.signal.event.warning.1.png) +![bpmn.signal.event.warning.1](../assets/bpmn/bpmn.signal.event.warning.1.png) The pattern described in the process above is not supported by BPMN. The idea is that the error thrown while performing the "do something" task is caught by the boundary error event, propagated to the parallel path of execution using the signal throw event and then interrupt the "do something in parallel" task. So far, Flowable would perform as expected. The signal would be propagated to the catching boundary event and interrupt the task. **However, due to the broadcast semantics of the signal, it would also be propagated to all other process instances that have subscribed to the signal event.** In this case, this might not be what we want. @@ -264,7 +264,7 @@ Such queries are called correlation queries and usually require knowledge about The following is an example of a process that can be started using two different messages: -![bpmn.start.message.event.example.1](assets/bpmn/bpmn.start.message.event.example.1.png) +![bpmn.start.message.event.example.1](../assets/bpmn/bpmn.start.message.event.example.1.png) This is useful if the process needs alternative ways to react to different start events, but eventually continues in a uniform way. @@ -307,7 +307,7 @@ A 'none' start event technically means that the trigger for starting the process A none start event is visualized as a circle with no inner icon (in other words, no trigger type). -![bpmn.none.start.event](assets/bpmn/bpmn.none.start.event.png) +![bpmn.none.start.event](../assets/bpmn/bpmn.none.start.event.png) #### XML representation @@ -337,7 +337,7 @@ A timer start event is used to create process instances at given time. It can be A timer start event is visualized as a circle with clock inner icon. -![bpmn.clock.start.event](assets/bpmn/bpmn.clock.start.event.png) +![bpmn.clock.start.event](../assets/bpmn/bpmn.clock.start.event.png) #### XML representation @@ -402,7 +402,7 @@ The messageName is the name given in the name attribute of the message element r A message start event is visualized as a circle with a message event symbol. The symbol is unfilled, to represent the catching (receiving) behavior. -![bpmn.start.message.event](assets/bpmn/bpmn.start.message.event.png) +![bpmn.start.message.event](../assets/bpmn/bpmn.start.message.event.png) #### XML representation @@ -440,7 +440,7 @@ The signalName that must be passed in the API is the name given in the name attr A signal start event is visualized as a circle with a signal event symbol. The symbol is unfilled, to represent the catching (receiving) behavior. -![bpmn.start.signal.event](assets/bpmn/bpmn.start.signal.event.png) +![bpmn.start.signal.event](../assets/bpmn/bpmn.start.signal.event.png) #### XML representation @@ -470,7 +470,7 @@ An error start event is always interrupting. An error start event is visualized as a circle with an error event symbol. The symbol is unfilled, to represent the catching (receiving) behavior. -![bpmn.start.error.event](assets/bpmn/bpmn.start.error.event.png) +![bpmn.start.error.event](../assets/bpmn/bpmn.start.error.event.png) #### XML representation @@ -494,7 +494,7 @@ A 'none' end event means that the *result* thrown when the event is reached is u A none end event is visualized as a circle with a thick border with no inner icon (no result type). -![bpmn.none.end.event](assets/bpmn/bpmn.none.end.event.png) +![bpmn.none.end.event](../assets/bpmn/bpmn.none.end.event.png) #### XML representation @@ -512,7 +512,7 @@ When process execution arrives at an **error end event**, the current path of ex An error end event is visualized as a typical end event (circle with thick border), with the error icon inside. The error icon is completely black, to indicate its throwing semantics. -![bpmn.error.end.event](assets/bpmn/bpmn.error.end.event.png) +![bpmn.error.end.event](../assets/bpmn/bpmn.error.end.event.png) #### XML representation @@ -560,7 +560,7 @@ There is an optional attribute *terminateAll* that can be added. When *true*, re A cancel end event visualized as a typical end event (circle with thick outline), with a full black circle inside. -![bpmn.terminate.end.event](assets/bpmn/bpmn.terminate.end.event.png) +![bpmn.terminate.end.event](../assets/bpmn/bpmn.terminate.end.event.png) #### XML representation @@ -582,7 +582,7 @@ The cancel end event can only be used in combination with a BPMN transaction sub A cancel end event is visualized as a typical end event (circle with thick outline), with the cancel icon inside. The cancel icon is completely black, to indicate its throwing semantics. -![bpmn.cancel.end.event](assets/bpmn/bpmn.cancel.end.event.png) +![bpmn.cancel.end.event](../assets/bpmn/bpmn.cancel.end.event.png) #### XML representation @@ -621,7 +621,7 @@ A timer boundary event acts as a stopwatch and alarm clock. When an execution ar A timer boundary event is visualized as a typical boundary event (circle on the border), with the timer icon on the inside. -![bpmn.boundary.timer.event](assets/bpmn/bpmn.boundary.timer.event.png) +![bpmn.boundary.timer.event](../assets/bpmn/bpmn.boundary.timer.event.png) #### XML Representation @@ -637,7 +637,7 @@ Please refer to [timer event definition](bpmn/ch07b-BPMN-Constructs.md#timer-eve In the graphical representation, the line of the circle is dotted as you can see in the example above: -![bpmn.non.interrupting.boundary.timer.event](assets/bpmn/bpmn.non.interrupting.boundary.timer.event.png) +![bpmn.non.interrupting.boundary.timer.event](../assets/bpmn/bpmn.non.interrupting.boundary.timer.event.png) A typical use case is sending an escalation email after a period of time, but without affecting the normal process flow. @@ -651,7 +651,7 @@ There is a key difference between the interrupting and non interrupting timer ev There is a known issue regarding concurrency when using boundary events of any type. Currently, it is not possible to have multiple outgoing sequence flows attached to a boundary event. A solution to this problem is to use one outgoing sequence flow that goes to a parallel gateway. -![bpmn.known.issue.boundary.event](assets/bpmn/bpmn.known.issue.boundary.event.png) +![bpmn.known.issue.boundary.event](../assets/bpmn/bpmn.known.issue.boundary.event.png) ### Error Boundary Event @@ -667,7 +667,7 @@ When an error event is caught, the activity on which the boundary event is defin A boundary error event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the error icon inside. The error icon is white, to indicate its *catch* semantics. -![bpmn.boundary.error.event](assets/bpmn/bpmn.boundary.error.event.png) +![bpmn.boundary.error.event](../assets/bpmn/bpmn.boundary.error.event.png) #### XML representation @@ -696,7 +696,7 @@ The **errorCode** is used to match the errors that are caught: The following example process shows how an error end event can be used. When the *'Review profitability'* user task is completed by saying that not enough information is provided, an error is thrown. When this error is caught on the boundary of the sub-process, all active activities within the *'Review sales lead'* sub-process are destroyed (even if *'Review customer rating'* had not yet been completed), and the *'Provide additional details'* user task is created. -![bpmn.boundary.error.example](assets/bpmn/bpmn.boundary.error.example.png) +![bpmn.boundary.error.example](../assets/bpmn/bpmn.boundary.error.example.png) This process is shipped as example in the demo setup. The process XML and unit test can be found in the *org.flowable.examples.bpmn.event.error* package. @@ -714,7 +714,7 @@ An attached intermediate *catching* [signal](bpmn/ch07b-BPMN-Constructs.md#signa A boundary signal event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the signal icon inside. The signal icon is white (unfilled), to indicate its *catch* semantics. -![bpmn.boundary.signal.event](assets/bpmn/bpmn.boundary.signal.event.png) +![bpmn.boundary.signal.event](../assets/bpmn/bpmn.boundary.signal.event.png) #### XML representation @@ -738,7 +738,7 @@ An attached intermediate *catching* [message](bpmn/ch07b-BPMN-Constructs.md#mess A boundary message event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the message icon inside. The message icon is white (unfilled), to indicate its *catch* semantics. -![bpmn.boundary.message.event](assets/bpmn/bpmn.boundary.message.event.png) +![bpmn.boundary.message.event](../assets/bpmn/bpmn.boundary.message.event.png) Note that boundary message event can be both interrupting (right-hand side) and non-interrupting (left-hand side). @@ -770,7 +770,7 @@ An attached intermediate *catching* cancel event on the boundary of a transactio A cancel boundary event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the cancel icon inside. The cancel icon is white (unfilled), to indicate its *catching* semantics. -![bpmn.boundary.cancel.event](assets/bpmn/bpmn.boundary.cancel.event.png) +![bpmn.boundary.cancel.event](../assets/bpmn/bpmn.boundary.cancel.event.png) #### XML representation @@ -806,7 +806,7 @@ A compensation boundary event has a different activation policy from other bound A compensation boundary event is visualized as a typical intermediate event (circle with smaller circle inside) on the boundary, with the compensation icon inside. The compensation icon is white (unfilled), to indicate its *catching* semantics. In addition to a compensation boundary event, the following figure shows a compensation handler associated with the boundary event using a unidirectional association: -![bpmn.boundary.compensation.event](assets/bpmn/bpmn.boundary.compensation.event.png) +![bpmn.boundary.compensation.event](../assets/bpmn/bpmn.boundary.compensation.event.png) #### XML representation @@ -847,7 +847,7 @@ A timer intermediate event acts as a stopwatch. When an execution arrives at a c A timer intermediate event is visualized as an intermediate catching event, with the timer icon on the inside. -![bpmn.intermediate.timer.event](assets/bpmn/bpmn.intermediate.timer.event.png) +![bpmn.intermediate.timer.event](../assets/bpmn/bpmn.intermediate.timer.event.png) #### XML Representation @@ -873,7 +873,7 @@ An intermediate *catching* [signal](bpmn/ch07b-BPMN-Constructs.md#signal-event-d An intermediate signal catch event is visualized as a typical intermediate event (circle with smaller circle inside), with the signal icon inside. The signal icon is white (unfilled), to indicate its *catch* semantics. -![bpmn.intermediate.signal.catch.event](assets/bpmn/bpmn.intermediate.signal.catch.event.png) +![bpmn.intermediate.signal.catch.event](../assets/bpmn/bpmn.intermediate.signal.catch.event.png) #### XML representation @@ -897,7 +897,7 @@ An intermediate *catching* [message](bpmn/ch07b-BPMN-Constructs.md#message-event An intermediate catching message event is visualized as a typical intermediate event (circle with smaller circle inside), with the message icon inside. The message icon is white (unfilled), to indicate its *catch* semantics. -![bpmn.intermediate.message.catch.event](assets/bpmn/bpmn.intermediate.message.catch.event.png) +![bpmn.intermediate.message.catch.event](../assets/bpmn/bpmn.intermediate.message.catch.event.png) #### XML representation @@ -929,7 +929,7 @@ An intermediate throwing event is defined with: The following process diagram shows a simple example of an intermediate none event, which is often used to indicate some state achieved in the process. -![bpmn.intermediate.none.event](assets/bpmn/bpmn.intermediate.none.event.png) +![bpmn.intermediate.none.event](../assets/bpmn/bpmn.intermediate.none.event.png) This can be a good hook to monitor some KPIs, by adding an [execution listener](bpmn/ch07b-BPMN-Constructs.md#execution-listener). @@ -957,7 +957,7 @@ In Flowable, the signal is broadcast to all active handlers (in other words, all An intermediate signal throw event is visualized as a typical intermediate event (circle with smaller circle inside), with the signal icon inside. The signal icon is black (filled), to indicate its *throw* semantics. -![bpmn.intermediate.signal.throw.event](assets/bpmn/bpmn.intermediate.signal.throw.event.png) +![bpmn.intermediate.signal.throw.event](../assets/bpmn/bpmn.intermediate.signal.throw.event.png) #### XML representation @@ -997,7 +997,7 @@ An intermediate *throwing* compensation event can be used to trigger compensatio **Note:** If compensation is thrown within a scope that contains a sub-process, and the sub-process contains activities with compensation handlers, compensation is only propagated to the sub-process if it has completed successfully when compensation is thrown. If some of the activities nested inside the sub-process have completed and have attached compensation handlers, the compensation handlers are not executed if the sub-process containing these activities is not completed yet. Consider the following example: -![bpmn.throw.compensation.example1](assets/bpmn/bpmn.throw.compensation.example1.png) +![bpmn.throw.compensation.example1](../assets/bpmn/bpmn.throw.compensation.example1.png) In this process we have two concurrent executions: one executing the embedded sub-process and one executing the "charge credit card" activity. Let’s assume both executions are started and the first concurrent execution is waiting for a user to complete the "review bookings" task. The second execution performs the "charge credit card" activity and an error is thrown, which causes the "cancel reservations" event to trigger compensation. At this point the parallel sub-process is not yet completed which means that the compensation event is not propagated to the sub-process and consequently the "cancel hotel reservation" compensation handler is not executed. If the user task (and therefore the embedded sub-process) completes before the "cancel reservations" is performed, compensation is propagated to the embedded sub-process. @@ -1021,7 +1021,7 @@ In this process we have two concurrent executions: one executing the embedded su An intermediate compensation throw event is visualized as a typical intermediate event (circle with smaller circle inside), with the compensation icon inside. The compensation icon is black (filled), to indicate its *throw* semantics. -![bpmn.intermediate.compensation.throw.event](assets/bpmn/bpmn.intermediate.compensation.throw.event.png) +![bpmn.intermediate.compensation.throw.event](../assets/bpmn/bpmn.intermediate.compensation.throw.event.png) #### XML representation @@ -1047,7 +1047,7 @@ A sequence flow is the connector between two elements of a process. After an ele A sequence flow is visualized as an arrow going from the source element towards the target element. The arrow always points towards the target. -![bpmn.sequence.flow](assets/bpmn/bpmn.sequence.flow.png) +![bpmn.sequence.flow](../assets/bpmn/bpmn.sequence.flow.png) ### XML representation @@ -1067,7 +1067,7 @@ A sequence flow can have a condition defined on it. When a BPMN 2.0 activity is A conditional sequence flow is visualized as a regular sequence flow, with a small diamond at the beginning. The condition expression is shown next to the sequence flow. -![bpmn.conditional.sequence.flow](assets/bpmn/bpmn.conditional.sequence.flow.png) +![bpmn.conditional.sequence.flow](../assets/bpmn/bpmn.conditional.sequence.flow.png) #### XML representation @@ -1099,7 +1099,7 @@ Currently, conditionalExpressions can **only be used with UEL**. Detailed inform The Flowable distribution contains the following example process using value and method expressions (see *org.flowable.examples.bpmn.expression)*: -![bpmn.uel expression.on.seq.flow](assets/bpmn/bpmn.uel-expression.on.seq.flow.png) +![bpmn.uel expression.on.seq.flow](../assets/bpmn/bpmn.uel-expression.on.seq.flow.png) ### Default sequence flow @@ -1111,7 +1111,7 @@ All BPMN 2.0 tasks and gateways can have a **default sequence flow**. This seque A default sequence flow is visualized as a regular sequence flow, with a 'slash' marker at the beginning. -![bpmn.default.sequence.flow](assets/bpmn/bpmn.default.sequence.flow.png) +![bpmn.default.sequence.flow](../assets/bpmn/bpmn.default.sequence.flow.png) #### XML representation @@ -1137,7 +1137,7 @@ A gateway is used to control the flow of execution (or as the BPMN 2.0 describes A gateway is graphically visualized as a diamond shape, with an icon inside. The icon shows the type of gateway. -![bpmn.gateway](assets/bpmn/bpmn.gateway.png) +![bpmn.gateway](../assets/bpmn/bpmn.gateway.png) ### Exclusive Gateway @@ -1151,7 +1151,7 @@ An exclusive gateway (also called the *XOR gateway* or more technical the *exclu An exclusive gateway is visualized as a typical gateway (a diamond shape) with an 'X' icon inside, referring to the *XOR* semantics. Note that a gateway without an icon inside defaults to an exclusive gateway. The BPMN 2.0 specification does not permit use of both the diamond with and without an X in the same process definition. -![bpmn.exclusive.gateway.notation](assets/bpmn/bpmn.exclusive.gateway.notation.png) +![bpmn.exclusive.gateway.notation](../assets/bpmn/bpmn.exclusive.gateway.notation.png) #### XML representation @@ -1159,7 +1159,7 @@ The XML representation of an exclusive gateway is straight-forward: one line def Take, for example, the following model: -![bpmn.exclusive.gateway](assets/bpmn/bpmn.exclusive.gateway.png) +![bpmn.exclusive.gateway](../assets/bpmn/bpmn.exclusive.gateway.png) Which is represented in XML as follows: @@ -1197,7 +1197,7 @@ Note that a parallel gateway can have **both fork and join behavior**, if there A parallel gateway is visualized as a gateway (diamond shape) with the 'plus' symbol inside, referring to the 'AND' semantics. -![bpmn.parallel.gateway](assets/bpmn/bpmn.parallel.gateway.png) +![bpmn.parallel.gateway](../assets/bpmn/bpmn.parallel.gateway.png) #### XML representation @@ -1250,7 +1250,7 @@ When these two tasks are completed, the second parallel gateway will join the tw Note that a parallel gateway does not need to be 'balanced' (a matching number of incoming/outgoing sequence flow for corresponding parallel gateways). A parallel gateway will simply wait for all incoming sequence flows and create a concurrent path of execution for each outgoing sequence flow, not influenced by other constructs in the process model. So, the following process is legal in BPMN 2.0: -![bpmn.unbalanced.parallel.gateway](assets/bpmn/bpmn.unbalanced.parallel.gateway.png) +![bpmn.unbalanced.parallel.gateway](../assets/bpmn/bpmn.unbalanced.parallel.gateway.png) ### Inclusive Gateway @@ -1270,7 +1270,7 @@ Note that an inclusive gateway can have **both fork and join behavior**, if ther An inclusive gateway is visualized as a gateway (diamond shape) with the 'circle' symbol inside. -![bpmn.inclusive.gateway](assets/bpmn/bpmn.inclusive.gateway.png) +![bpmn.inclusive.gateway](../assets/bpmn/bpmn.inclusive.gateway.png) #### XML representation @@ -1348,7 +1348,7 @@ Note the sequence flows running out of an Event-based Gateway are different from An Event-based Gateway is visualized as a diamond shape like other BPMN gateways with a special icon inside. -![bpmn.event.based.gateway.notation](assets/bpmn/bpmn.event.based.gateway.notation.png) +![bpmn.event.based.gateway.notation](../assets/bpmn/bpmn.event.based.gateway.notation.png) #### XML representation @@ -1358,7 +1358,7 @@ The XML element used to define an Event-based Gateway is eventBasedGateway. The following process is an example of a process with an Event-based Gateway. When the execution arrives at the Event-based Gateway, process execution is suspended. In addition, the process instance subscribes to the alert signal event and creates a timer that fires after 10 minutes. This effectively causes the process engine to wait for ten minutes for a signal event. If the signal occurs within 10 minutes, the timer is cancelled and execution continues after the signal. If the signal is not fired, execution continues after the timer and the signal subscription is canceled. -![bpmn.event.based.gateway.example](assets/bpmn/bpmn.event.based.gateway.example.png) +![bpmn.event.based.gateway.example](../assets/bpmn/bpmn.event.based.gateway.example.png) @@ -735,7 +735,7 @@ Properties: A milestone is visualized as a rounded rectangle (more rounded than a task): -![cmmn.milestone](assets/cmmn/cmmn.milestone.png) +![cmmn.milestone](../assets/cmmn/cmmn.milestone.png) ### Case task @@ -755,7 +755,7 @@ Properties: A case task is visualized as a rounded rectangle with a case icon in the top left corner: -![cmmn.casetask](assets/cmmn/cmmn.casetask.png) +![cmmn.casetask](../assets/cmmn/cmmn.casetask.png) ### Process task @@ -775,7 +775,7 @@ Properties: A process task is visualized as a rounded rectangle with an arrow icon in the top left corner: -![cmmn.processtask](assets/cmmn/cmmn.processtask.png) +![cmmn.processtask](../assets/cmmn/cmmn.processtask.png) A process task can be configured to have in- and out parameters, which take the form of *source/sourceExpression* and *target/targetExpression*. @@ -816,7 +816,7 @@ See [the section on sentry evaluation](cmmn/ch06-cmmn.md#sentry-evaluation) for An entry criterion is visualized as a diamond shape (white color inside) on the border of a plan item: -![cmmn.entrycriteria](assets/cmmn/cmmn.entrycriteria.png) +![cmmn.entrycriteria](../assets/cmmn/cmmn.entrycriteria.png) #### Exit criterion (exit sentry) @@ -833,7 +833,7 @@ See [the section on sentry evaluation](cmmn/ch06-cmmn.md#sentry-evaluation) for An exit criterion is visualized as a diamond shape (white color inside) on the border of a plan item: -![cmmn.exitcriteria](assets/cmmn/cmmn.exitcriteria.png) +![cmmn.exitcriteria](../assets/cmmn/cmmn.exitcriteria.png) Beyond the specification, Flowable supports additional attributes on an exit sentry which adds more flexibility and options on how a plan item is terminated when the exit sentry triggers. @@ -877,7 +877,7 @@ Full example on how to use the exit event type attribute in combination with a u It contains two important parts: the *flowable:exitEventType="complete"* attribute on the exit criterion and the *flowable:availableCondition="${cmmn:isStageCompletable()}"* on the user event listener which makes the listener only available, if the stage is currently completable, otherwise it is unavailable. Once the user listener triggers, the exit sentry is executed and will complete the stage, not terminate it and leave it in *completed* state, triggering the *complete* event, not the *exit* event. -![cmmn exit sentry on stage](assets/cmmn/cmmn-exit-sentry-on-stage.png) +![cmmn exit sentry on stage](../assets/cmmn/cmmn-exit-sentry-on-stage.png) Here you find the CMMN model in XML: @@ -945,7 +945,7 @@ Note that setting a *start trigger* for the timer event listener does not have a A timer event listener is visualized as circle with a clock icon inside: -![cmmn.timereventlistener](assets/cmmn/cmmn.timereventlistener.png) +![cmmn.timereventlistener](../assets/cmmn/cmmn.timereventlistener.png) #### User Event Listener @@ -955,7 +955,7 @@ A typical use case for a user event listener are buttons in a UI that a user can When the event is triggered an *Occur* event is thrown to which sentries can listener to. Like timer event listeners, it has a much simpler lifecycle that a *task*. -![cmmn.usereventlistener](assets/cmmn/cmmn.usereventlistener.png) +![cmmn.usereventlistener](../assets/cmmn/cmmn.usereventlistener.png) User event listeners can be queried using the *org.flowable.cmmn.api.runtime.UserEventListenerInstanceQuery*. Such a query can be created by calling the *cmmnRuntimeService.createUserEventListenerInstanceQuery()* method. Note that a user event listener is also a plan item instance, which means it can also be queried through the *org.flowable.cmmn.api.runtime.PlanItemInstanceQuery* API. @@ -965,7 +965,7 @@ A user event listener can be completed by calling the *cmmnRuntimeService.comple A generic event listener is used to typically model a programmatic interaction (e.g. a external system that calls out to change something in a case instance). -![cmmn.generic event listener](assets/cmmn/cmmn.generic-event-listener.png) +![cmmn.generic event listener](../assets/cmmn/cmmn.generic-event-listener.png) The API to retrieve and complete these event listeners is on the *CmmnRuntimeService*: @@ -981,7 +981,7 @@ Note that generic event listeners are not part of the CMMN specification, but ar The engine will automatically detect when event listeners (user or timer) are not useful anymore. Take for example the following case definition: -![cmmn.user event listener removal 1](assets/cmmn/cmmn.user-event-listener-removal-1.png) +![cmmn.user event listener removal 1](../assets/cmmn/cmmn.user-event-listener-removal-1.png) Here, the *First stage* contains two human tasks (A and B) and it can be exited by a user when the *Stop first stage* user event is triggered. However, when both tasks A and B are completed, the stage will also complete. If now the user event listener would be triggered, there is nothing that listens to this event anymore. @@ -989,19 +989,19 @@ The engine will detect this and terminate the user event automatically. The same mechanism also works for event listeners that are referenced by entry sentries: -![cmmn.user event listener removal 2](assets/cmmn/cmmn.user-event-listener-removal-2.png) +![cmmn.user event listener removal 2](../assets/cmmn/cmmn.user-event-listener-removal-2.png) In this case, in the case that *EventListenerA* would be triggered, *EventListenerB* is terminated (as nothing is listening to its occurrence anymore). Or, when timer and user event listeners are mixed, the one that is triggered first will also cause the removal of others (when they are not referenced somewhere else): -![cmmn.user event listener removal 3](assets/cmmn/cmmn.user-event-listener-removal-3.png) +![cmmn.user event listener removal 3](../assets/cmmn/cmmn.user-event-listener-removal-3.png) Here, the timer will be removed in case the user event is triggered first (and vice versa). The detection also takes in account plan items that have not yet been created. Take for example the following case definition: -![cmmn.user event listener removal 4](assets/cmmn/cmmn.user-event-listener-removal-4.png) +![cmmn.user event listener removal 4](../assets/cmmn/cmmn.user-event-listener-removal-4.png) Here, human task *C* is not yet created when a case instance is started for this case definition. The user event listener will not be removed as long that *C* has a parent stage that is in a non-terminal state, as this means that the event could still be listened to in the future. @@ -1009,7 +1009,7 @@ Here, human task *C* is not yet created when a case instance is started for this All types of event listeners can be configured to have a **available condition**: an expressions that will guard the available state of the event listener. To explain the use case, take the following case definition: -![cmmn.create condition](assets/cmmn/cmmn.create-condition.png) +![cmmn.create condition](../assets/cmmn/cmmn.create-condition.png) When the case instance is started, Stage 1 (as it has no entry criteria) will be moving immediately from *available* to *active*. Similar story for human task A. Human task B will move from *available* to *enabled* as it’s manually activated. @@ -1037,7 +1037,7 @@ If the plan item has entry criteria, the behavior is different. The repetition r Take, for example, the following timer event listener followed by a human task. The sentry has one entry criterion for the *occur* event of the timer event listener. Note that enabling and setting the repetition rule on the task has a visual indicator at the bottom of the rectangle. -![cmmn.repeatingtimereventlistener](assets/cmmn/cmmn.repeatingtimereventlistener.png) +![cmmn.repeatingtimereventlistener](../assets/cmmn/cmmn.repeatingtimereventlistener.png) If the timer event listener is repeating (for example, *R/PT1H*), the *occur* event will be fired every hour. When the repetition rule expression of the human task evaluates to true, a new human task instance will be created each hour. @@ -1120,7 +1120,7 @@ When no expression is set, but the manual activation is enabled (for example, th Stages and all task types can be marked for manual activation. Visually, the task or stage will get a 'play' icon (small triangle pointing to the right) to indicate an end-user will have to manually activate it: -![cmmn.manual activation](assets/cmmn/cmmn.manual-activation.png) +![cmmn.manual activation](../assets/cmmn/cmmn.manual-activation.png) Normally, when a sentry for a plan item is satisfied (or the plan item doesn’t have any sentries) the plan item instance is automatically moved to the *ACTIVE* state. When a manual activation is set though, and it evaluates to true, the plan item instance now becomes *ENABLED* instead of *ACTIVE*. As the name implies, the idea behind this is that end-users manually have to activate the plan item instance. A typical use case is showing a list of buttons of potential plan item instances that can currently be started by the end user. @@ -1162,13 +1162,13 @@ The *required rule* works in conjunction with the *autoComplete* attribute on th A *stage plan item instance* has a **completable** property that can be used to see whether or not the conditions for completion are satisfied. Take, for example, the following simple stage and assume that the sentry for the *required task* evaluates to true and the other one to false. This means that the left plan item instance will be active while the right one will be in the *available* state. -![cmmn.completeable stage](assets/cmmn/cmmn.completeable-stage.png) +![cmmn.completeable stage](../assets/cmmn/cmmn.completeable-stage.png) Calling *cmmnRuntimeService.completeStagePlanItemInstance(String stagePlanItemInstanceId)* will not be possible for the stage (an exception will be thrown) as it has one active child plan item instance. When this user task on the left is completed, the *completeStagePlanItemInstance* can now be called, as no child plan item instances are currently active. However, by itself, the stage will not automatically complete as the right user task is in the available state. If the previous stage is changed to be **autocompletable** (this is visualised by a black rectangle at the bottom of the stage) and the plan item on the left is changed to be required (this is visualised using an exclamation mark), the behavior will be different: -![cmmn.completeable stage02](assets/cmmn/cmmn.completeable-stage02.png) +![cmmn.completeable stage02](../assets/cmmn/cmmn.completeable-stage02.png) - If the left plan item instance is active (sentry is true) and the right is not (sentry is false). In this case, when the left user task is completed, the stage instance will auto complete as it has no active child plan item instances and all required plan item instances are in an end state @@ -1182,7 +1182,7 @@ If the previous stage is changed to be **autocompletable** (this is visualised b Note that the manual activation rule works independently of the required rule. For example, given the following stage: -![cmmn.completeable stage03](assets/cmmn/cmmn.completeable-stage03.png) +![cmmn.completeable stage03](../assets/cmmn/cmmn.completeable-stage03.png) Here, user task D is required and user task B is manually activated. @@ -1290,7 +1290,7 @@ Sentries consist of two parts: Take for example the following case definition: -![cmmn.sentry eval 01](assets/cmmn/cmmn.sentry-eval-01.png) +![cmmn.sentry eval 01](../assets/cmmn/cmmn.sentry-eval-01.png) Assume (not shown in the diagram here) @@ -1343,7 +1343,7 @@ The default behavior (see previous section) will remember which parts have been There is an alternative mode of sentry triggering that is called **"onEvent"**. In this mode, the engine will have memory with regards to parts of the sentry and will **not remember** any part that was satisfied in the past. This is sometimes needed in advanced use cases. Take for example the following example: -![cmmn.sentry eval 02](assets/cmmn/cmmn.sentry-eval-02.png) +![cmmn.sentry eval 02](../assets/cmmn/cmmn.sentry-eval-02.png) Here, the case model has a stage with with three substages. All substage are repeating. Substage B and C have an entry sentry for the completion of stage B. Also (not visually shown), both sentries have a condition that depends on a variable. @@ -1353,7 +1353,7 @@ Concretely, in the example here, the condition of the entry sentries will be eva Do note that the engine deems all events to happen simultaneously when it comes to evaluating sentries. Take the following case definition: -![cmmn.sentry eval 03](assets/cmmn/cmmn.sentry-eval-03.png) +![cmmn.sentry eval 03](../assets/cmmn/cmmn.sentry-eval-03.png) Assume that all sentries use the *triggerMode onEvent* setting. If task A is completed, this exits task B. Task C will now exit too. So, even though there are two distinct lifecycle events (A being completed and B being exited) and one might assume that *onEvent* literally means that there are two distinct evaluations happening where the memory of the other part of the exit sentry on task C is forgotten, the engine is smart enough to see that they are part of the same evaluation cycle and task C will be exited too. diff --git a/docs/docusaurus/docs/cmmn/ch07-architecture.md b/docs/docusaurus/docs/cmmn/ch07-architecture.md index 1864b3251aa..7f3efe9cec7 100644 --- a/docs/docusaurus/docs/cmmn/ch07-architecture.md +++ b/docs/docusaurus/docs/cmmn/ch07-architecture.md @@ -7,7 +7,7 @@ This chapter gives a short introduction to the internals of the CMMN engine from The CMMN engine, as shown in the diagram below, is one of the engines that is part of the Flowable engines eco-system and is designed in a similar way as the other engines. The CMMN engine builds upon CMMN specific services and the shared services: the task, variable, identity and job services, which are independent from the engines. On a lower level the entity- and datamanager layer takes care of the low-level persistence, equivalent to the other engines. -![cmmn.architecture](assets/cmmn/cmmn.architecture.png) +![cmmn.architecture](../assets/cmmn/cmmn.architecture.png) By using the shared services, this also means that for example tasks from both the BPMN and the CMMN engine will end up together and can be queried and managed through the same API. Similarly for the async executor: timers and async jobs use the same logic and even can be managed by a central executor. @@ -15,7 +15,7 @@ The shared services architecture has a second benefit. When the engines are used The CMMN engine is designed with the same principles as the other engines of the Flowable project. The diagram below gives a high-level overview of the different components involved when working with the CMMN Engine: -![cmmn.api call flow](assets/cmmn/cmmn.api-call-flow.png) +![cmmn.api call flow](../assets/cmmn/cmmn.api-call-flow.png) From a high level point of view: diff --git a/docs/docusaurus/docs/dmn/ch06-DMN-Introduction.md b/docs/docusaurus/docs/dmn/ch06-DMN-Introduction.md index 13c287e6d39..6842b997627 100644 --- a/docs/docusaurus/docs/dmn/ch06-DMN-Introduction.md +++ b/docs/docusaurus/docs/dmn/ch06-DMN-Introduction.md @@ -34,15 +34,15 @@ We’ll implement a very simple use case: determining the discount percentage ba Start by opening the decision tables section within the Flowable modeler. -![decision tables 1](assets/dmn/decision_tables_1.png) +![decision tables 1](../assets/dmn/decision_tables_1.png) And select **Create Decision Table**. -![decision tables 2](assets/dmn/decision_tables_2.png) +![decision tables 2](../assets/dmn/decision_tables_2.png) Provide a decision table name and a unique decision table key and select **Create new decision table**. -![decision tables 3](assets/dmn/decision_tables_3.png) +![decision tables 3](../assets/dmn/decision_tables_3.png) You’re now ready to define your decision table. Let’s describe what is presented within the editor. @@ -85,11 +85,11 @@ There are 7 hit policies available; The header of the decision table itself is divided in two sections; blue and green. In the blue section are the **input expressions**; the green the **output expressions**. -![decision tables 4](assets/dmn/decision_tables_4.png) +![decision tables 4](../assets/dmn/decision_tables_4.png) Within an input expression, you can define the variable that will be used in the expression of the rule input entries (explained below). It’s possible to define multiple input expressions by selecting **Add Input** (right click option menu or by clicking the plus icon). -![decision tables 5](assets/dmn/decision_tables_5.png) +![decision tables 5](../assets/dmn/decision_tables_5.png) Within an output expression, you can define what variable will be created to form the result of a decision table execution (the value of the variable will be determined by the output entry expression; explained below). It’s possible to define multiple output expressions by selecting **Add Output** (right click option menu or by clicking the plus icon). @@ -102,23 +102,23 @@ A input entry is an expression that will be evaluated against the input variable > > The DMN specification defines an expression language: (S)-FEEL. Currently, we do not supported this part of the specification. Within Flowable DMN, we use JUEL as the expression language. -![decision tables 6](assets/dmn/decision_tables_6.png) +![decision tables 6](../assets/dmn/decision_tables_6.png) To enter an expression, double-click on the corresponding cell. In this example, the expression *== BRONZE* is entered. Combined with the variable defined in the corresponding input expression (column header), this will result at runtime in the full expression *customerCat == "BRONZE"*. -![decision tables 7](assets/dmn/decision_tables_7.png) +![decision tables 7](../assets/dmn/decision_tables_7.png) To enter an output expression, double-click the corresponding cell. In this example the expression *5* is entered. This is actually more like an implicit assignment. The value 5 will be assigned to the variable in the corresponding output entry (column) when all input entries of that rule are evaluated true. We can then continue completing the decision table by adding more rules (by selecting Add Rule). -![decision tables 8](assets/dmn/decision_tables_8.png) +![decision tables 8](../assets/dmn/decision_tables_8.png) In our example, rule 4 has an empty input entry. Empty input entries will be evaluated by the engine as true. This means that if none of the other rules are valid, the outcome of rule 4 will be the output of this decision table. In this case, variable **discountPerc** will have value **0**. -![decision tables 9](assets/dmn/decision_tables_9.png) +![decision tables 9](../assets/dmn/decision_tables_9.png) The decision table can now be saved. Provide a unique Decision Table key. @@ -126,7 +126,7 @@ The decision table can now be saved. Provide a unique Decision Table key. The newly created decision table can be used in a BPMN2.0 process by including a **Decision task** and selecting the **Decision table reference**. -![decision tables 10](assets/dmn/decision_tables_10.png) +![decision tables 10](../assets/dmn/decision_tables_10.png) In the process above, the process has a start form that will provide the **customer category** to the process instance (and thus to the decision table). The **Display Discount** user task displays the result of the decision table with an expression form field, using the expression; ${discountperc}. diff --git a/docs/docusaurus/website/README.md b/docs/docusaurus/website/README.md index 3487a7d99a7..4a386933d84 100644 --- a/docs/docusaurus/website/README.md +++ b/docs/docusaurus/website/README.md @@ -2,6 +2,8 @@ To install docusaurus globally: `yarn global add docusaurus` +To install dependency before run: `npm install` + To run the docs in dev mode: `yarn start` To build the docs: `yarn build` \ No newline at end of file